C基础 旋转数组查找题目
前言 - 引言
题目:
一类有序数组旋转查值问题.
例如:
有序数组 [ , , , , , , , , ] 旋转后为 [ , , , , , , , , ]
如何从中找出一个值索引, not found return -.
(同事面试时手写最简单一题, 回来和我说了一下, 就记下做个终结者系列)
这种旋转数组有个特点. 大家看图

相信大家豁然开朗了. 这里给个网上烂大街答案
//
// [1, 2, 3, 5, 5, 7, 7, 8, 9]
// 升序数组翻转后
// [5, 7, 7, 8, 9, 1, 2, 3, 5]
// 查找 value, return index, not found return -1;
//
int
search(int a[], int len, int v) {
int begin, end, mid;
// 异常判断
if (a == NULL || len <= )
return -; begin = ;
end = len;
while (begin < end) {
mid = (begin + end) / ;
if (a[mid] == v)
return mid; if (a[begin] < a[mid]) {
// 左边有序 [begin, mid]
if (a[begin] <= v && v < a[mid])
end = mid;
else
begin = mid + ;
} else if (a[begin] > a[mid]) {
// 右边有序 [mid, end)
if (a[mid] < v && v <= a[end - ])
begin = mid + ;
else
end = mid;
} else {
++begin;
}
} // 没有找到
return -;
}
这里使用 [begin, end) 二分法技巧. 代码支持升序旋转重复数组. 最坏情况(全重复)算法复杂度是 O(n).
不过有个问题, 如果不知道是升序 asc 还是降序 desc. 那就需要额外判断了.
// search_sort_state - 排序状态 -1 faild, 0 desc, 1 asc
static int search_sort_state(int a[], int len) {
int state, i, s[];
if (a == NULL || len <= )
return -;
// 默认 desc 降序
if (len == )
return ;
// 1, 2 asc 升序, 但必须反转为 2, 1 变成降序. 因而当前降序 desc 原本就是升序 asc
if (len == )
return a[] > a[]; // 摘取不重复的3个内容
s[] = a[]; // 开始找 s[1]
for (i = ; i < len; ++i) {
if (a[i] == s[])
continue;
break;
}
// 所有值都一样, 走默认降序
if (i >= len)
return ; s[] = a[i];
// 开始找 s[2]
while (i < len) {
if (a[i] == s[] || a[i] == s[]) {
++i;
continue;
}
break;
}
// 只有两个不一样的值, 走默认降序
if (i >= len)
return s[] > s[]; s[] = a[i]; state = ;
state += s[] > s[] ? : -;
state += s[] > s[] ? : -;
state += s[] > s[] ? : -;
return state >= ? : ;
}
最后是自己想得一个排序状态判别的算法(自我感觉巧妙). 试图找出不重复三个数. 例如
6 7 5 有
6 < 7 <
7 > 5 >
5 < 5 <
原生组合是 5 6 7
因而 < 居多是升序. > 居多是降序. (核心原因是旋转数组大小关系只改变一次)
正文 - 扩展
有了上面铺垫那我们开始码一个问题终结者代码. 希望有所感悟
// bsearch_asc - 二分查找升序查找
static int bsearch_asc(int a[], int begin, int end, int v) {
// 简单判断
if (begin >= end || v < a[begin] || v > a[end - ])
return -; // 二分查找
do {
int mid = (begin + end) / ;
int val = a[mid]; if (val == v)
return mid; if (val < v)
begin = mid + ;
else
end = mid;
} while (begin < end); return -;
} static int search_asc(int a[], int len, int v) {
int begin = , end = len;
// 异常判断
if (begin >= end)
return -; while (begin < end) {
int mid = (begin + end) / ;
if (a[mid] == v)
return mid; if (a[begin] < a[mid]) {
// 左边有序 [begin, mid]
if (a[begin] <= v && v < a[mid])
return bsearch_asc(a, begin, mid, v);
// 右边无序, 继续循环
begin = mid + ;
} else if (a[begin] > a[mid]) {
// 右边有序 [mid, end)
if (a[mid] < v && v <= a[end - ])
return bsearch_asc(a, mid + , end, v);
// 左边无须, 继续循环
end = mid;
} else {
++begin;
}
} // 没有找到
return -;
} // bsearch_desc - 二分查找降序查找
static int bsearch_desc(int a[], int begin, int end, int v) {
// 简单判断
if (begin >= end || v > a[begin] || v < a[end - ])
return -; // 二分查找
do {
int mid = (begin + end) / ;
int val = a[mid]; if (val == v)
return mid; if (val > v)
begin = mid + ;
else
end = mid;
} while (begin < end); return -;
} static int search_desc(int a[], int len, int v) {
int begin = , end = len; while (begin < end) {
int mid = (begin + end) / ;
if (a[mid] == v)
return mid; if (a[begin] > a[mid]) {
// 左边有序 [begin, mid]
if (a[begin] >= v && v > a[mid])
return bsearch_desc(a, begin, mid, v);
// 右边无序, 继续循环
begin = mid + ;
} else if (a[begin] < a[mid]) {
// 右边有序 [mid, end)
if (a[mid] > v && v >= a[end - ])
return bsearch_desc(a, mid + , end, v);
// 左边无须, 继续循环
end = mid;
} else {
++begin;
}
} // 没有找到
return -;
}
//
// 题目:
// 一类有序数组旋转查值问题.
// 例如:
// 有序数组 [ 1, 2, 3, 5, 5, 7, 7, 8, 9 ] 旋转后为 [ 5, 7, 7, 8, 9, 1, 2, 3, 5 ]
// 如何从中找出一个值索引, not found return -1.
int
search_upgrade(int a[], int len, int v) {
int state, i, s[];
if (a == NULL || len <= )
return -;
// 默认 desc 降序
if (len == ) {
if (a[] == v)
return ;
return -;
} if (len == ) {
if (a[] == v)
return ;
if (a[] == v)
return ;
return -;
} // 摘取不重复的3个内容
s[] = a[]; // 开始找 s[1]
for (i = ; i < len; ++i) {
if (a[i] == s[])
continue;
break;
}
// 所有值都一样, 走默认降序
if (i >= len) {
if (s[] == v)
return ;
return -;
} s[] = a[state = i];
// 开始找 s[2]
while (i < len) {
if (a[i] == s[] || a[i] == s[]) {
++i;
continue;
}
break;
}
// 只有两个不一样的值, 走默认降序
if (i >= len) {
if (s[] == v)
return ;
if (s[] == v)
return state;
return -;
} s[] = a[i];
state = ;
state += s[] > s[] ? : -;
state += s[] > s[] ? : -;
state += s[] > s[] ? : -; // desc 降序, 旋转
if (state >= )
return search_desc(a, len, v);
// asc 升序, 旋转
return search_asc(a, len, v);
}
不同分支不同代码, 针对性强. 代码最坏的情况是 O(n).
这里不妨来个测试演示
#include <stdio.h>
#include <stdlib.h> #define LEN(a) (sizeof(a)/sizeof(*a)) // print - 数据内容打印
#define INT_BR (15)
static void print(int a[], int len) {
int i = ;
while (i < len) {
printf(" %d", a[i]);
if (!(++i % INT_BR))
putchar('\n');
}
if (i % INT_BR)
putchar('\n');
} int search_upgrade(int a[], int len, int v); // sort - 旋转查找
int main(int argc, char * argv[]) {
int i, v;
int a[] = { , , , , , , , , };
print(a, LEN(a));
// 开始测试
v = ;
i = search_upgrade(a, LEN(a), v);
printf("%d -> %d\n", v, i);
v = ;
i = search_upgrade(a, LEN(a), v);
printf("%d -> %d\n", v, i); v = ;
i = search_upgrade(a, LEN(a), v);
printf("%d -> %d\n", v, i); v = ;
i = search_upgrade(a, LEN(a), v);
printf("%d -> %d\n", v, i); v = ;
i = search_upgrade(a, LEN(a), v);
printf("%d -> %d\n", v, i); int b[] = { , , , , , , , , , , , , };
print(b, LEN(b));
// 开始测试
v = ;
i = search_upgrade(b, LEN(b), v);
printf("%d -> %d\n", v, i); v = ;
i = search_upgrade(b, LEN(b), v);
printf("%d -> %d\n", v, i); v = ;
i = search_upgrade(b, LEN(b), v);
printf("%d -> %d\n", v, i); v = ;
i = search_upgrade(b, LEN(b), v);
printf("%d -> %d\n", v, i); v = ;
i = search_upgrade(b, LEN(b), v);
printf("%d -> %d\n", v, i); return EXIT_SUCCESS;
}
当前输出结果如下
$ gcc -g -Wall sort.c ; ./a.out ->
->
-> -
->
-> - ->
->
->
->
-> -
后记 - 感谢
错误是难免的 ~ 欢迎指正 : )
小桥 - https://music.163.com/#/song?id=493042772
C基础 旋转数组查找题目的更多相关文章
- leetcode旋转数组查找 二分查找的变形
http://blog.csdn.net/pickless/article/details/9191075 Suppose a sorted array is rotated at some pivo ...
- leetcode python 033 旋转数组查找
## 假设升序,import random def find(y): l,m=len(y),0 while l>1: n=int(l/2) if y[0] ...
- (剑指Offer)面试题8:旋转数组的最小数字
题目: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转 ...
- (2)剑指Offer之二维数组查找和替换空格问题
一 二维数组查找 题目描述: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 问 ...
- 剑指offer—第二章算法之二分查找(旋转数组的最小值)
旋转数组的最小数字 题目:把一个数组最开始的若干元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如:数组{3,4,5,1,2}为{1,2,3,4, ...
- 剑指offer 6.查找和排序 旋转数组的最小数字
题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋 ...
- 28.earch in Rotated Sorted Array(排序旋转数组中查找)
Level: Medium 题目描述: Suppose an array sorted in ascending order is rotated at some pivot unknown to ...
- leetcode题解:Search in Rotated Sorted Array(旋转排序数组查找)
题目: Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 ...
- Python 迭代器&生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发
本节大纲 迭代器&生成器 装饰器 基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - ...
随机推荐
- [AT2401] [arc072_e] Alice in linear land
题目链接 AtCoder:https://arc072.contest.atcoder.jp/tasks/arc072_c 洛谷:https://www.luogu.org/problemnew/sh ...
- BZOJ 3527 力 | FFT
BZOJ 3527 力 | 分治 题意 给出数组q,$E_i = \sum_{i < j} \frac{q_i}{(i - j) ^ 2} - \sum_{i > j} \frac{q_i ...
- Satisfiability of Equality Equations - LeetCode
目录 题目链接 注意点 解法 小结 题目链接 Satisfiability of Equality Equations - LeetCode 注意点 必须要初始化pre 解法 解法一:典型的并查集算法 ...
- BZOJ4036 [HAOI2015]按位或 【minmax容斥 + 期望 + FWT】
题目链接 BZOJ4036 题解 好套路的题啊,,, 我们要求的,实际上是一个集合\(n\)个\(1\)中最晚出现的\(1\)的期望时间 显然\(minmax\)容斥 \[E(max\{S\}) = ...
- 关于Powershell对抗安全软件(转)
Windows PowerShell的强大,并且内置,在渗透过程中,也让渗透变得更加有趣.而安全软件的对抗查杀也逐渐开始针对powershell的一切行为.在https://technet.micro ...
- 控制对象的创建方式(禁止创建栈对象or堆对象)和创建的数量
我们知道,C++将内存划分为三个逻辑区域:堆.栈和静态存储区.既然如此,我称位于它们之中的对象分别为堆对象,栈对象以及静态对象.通常情况下,对象创建在堆上还是在栈上,创建多少个,这都是没有限制的.但是 ...
- java-----遇到问题------myeclipse----发布项目到tomcat中lib文件夹没有子项目产生ClassNotFoundException错误
情况 myeclipse发布项目到tomcat中lib文件夹没有子项目产生ClassNotFoundException错误. 这种情况一般是 .classpath文件设置的输出路径不对导致的. 1.. ...
- MYSQL指定用户访问指定数据库
1.使用navicat 1)首先使用root用户新建连接 2)新建mysql用户 3)点击权限,选择添加权限,出现MySQL中已存在的数据库列表,选择你要为该新建用户开放的数据库,此处选择“maiba ...
- composer install 出现的问题
今天克隆代码之后,在composer install 的时候出现了一些问题,在此记录一下. 错误代码如下: [root@localhost MarketingCenter]# composer ins ...
- 执行composer install 报错的解决办法
执行composer install后报以下错误: Loading composer repositories with package informationInstalling dependenc ...