题目描述:
请实现如下函数,查找一个“两段有序”的整数数组a中是否存在某个整数x,返回对应的数组下标。算法复杂度O(log2(n))注:“两段有序”的数组定义如下,将一个有序的数组从某个位置分成两段(分界点未知),然后把后面一段放在前、前面一段放在后 拼成一个新的数组,即为“两段有序”,示例如下:
原有序数组
4 | 7 | 9 | 10 | 24 | 35 | 65 | 73 | 88 | 90 |
从73分成两段,重新组成一个新的“两段有序”数组
73 | 88 | 90 | 4 | 7 | 9 | 10 | 24 | 35 | 65 |
解题思路:
1、像二分查找一样,取中间值,如果中间值同时小于等于两边的值,则可以将数组分为两段,数组的左段(left ----mid)为“两段有序“数组,右段(mid----right)为一个有序数组
接下来再判断待查找值,再右端还是左段,如果待查找值大于mid 小于right值(即在右段),则在有序数组中,则用二分查找 即可。
否则,将right = mid - 1重复即可。
2、如果中间值同时大于等于两边值,则可以将数组也分为两段,左段(left --- mid)为一个有序数组,而有段(mid----right)为一个”两段有序“数组。
接下来再判断待查找值,再右端还是左段,如果待查找值小于mid 大于left值(即在左段),则在有序数组中,则用二分查找 即可。
否则,将left = mid + 1重复即可。
至此:题目已解决。
源代码
//二分查找
int binary_search(int elems[], int left, int right,int x)
{
while (left <= right)
{
int mid = (right - left) / 2 + left;
if (elems[mid] == x)
{
return mid;
}
else if (elems[mid] < x)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
return -1;
}
int search(int *elems, int size, int x) {
int left = 0;
int right = size - 1;
while (left <= right)
{
int mid = (right - left) / 2 + left;
if (x == elems[mid] || x == elems[left] || x == elems[right])
{
if (x == elems[mid])
{
return mid;
}
return (x==elems[left] ? left : right);
}
//同时小于mid的右边是有序数组
if (elems[mid] <= elems[right] && elems[mid] <= elems[left])
{
//如果判断x在mid的右边 大于mid 小于right
if (elems[mid] < x && elems[right] > x)
{
//二分查找
return binary_search(elems, left, right ,x);
}
else//在“两段有序”数组的区间
{
right = mid - 1;
}
}
//同时大于mid的左边是有序
else if(elems[mid] >= elems[right] && elems[mid] >= elems[left])
{
//如何判断x在mid的右边小于mid 小于left
if (elems[mid] > x && elems[left] < x)
{
//二分查找
return binary_search(elems,left,right,x);
}
else//在”两段有序数组“数组区间
{
left = mid + 1;
}
}
}
return - 1;
}
int main()
{
int elems[] = {73,88,90,4,7,9,10,24,35,65,67};
for (int i = 0; i < 11; i++)
cout << search(elems, 11, elems[i]) << endl;
system("pause");
return 0;
}