题目:把一个一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,给定一个K,输出K在旋转数组中的位置,如果K不存在输出-1
思路,这一题最笨的方法是将数组遍历一遍,但是这样的平均时间复杂度为O(N),肯定不是最好的解法,有O(logn)的解法比这个更好,方法就是使用优化后的二分查找的方法。
首先设定两个指针left,right,要求left永远指向旋转数组的左区域,right永远指向旋转数组的右区域,每次在取mid = (left + right)/2,那么mid要么属于左区域,要么属于右区域。
(1)当mid属于左区域的时候,num[mid] > num[left],当mid属于右区域的时候num[mid]<num[right],使用这两个条件就能判断mid是属于哪个区域,但是有一种特殊的情况,无法判断mid属于哪个区域,这个时候算法无法进行下去,遍历left到right这一部分的区域,就能找到k的所在
当判断完mid在哪个区域之后,判断K在哪个区域,方法同上,如果K的区域也无法判断,处理方法和mid一样。
当num[mid] == num[K]的时候,直接返回mid就好了,假如不等,进入下面的步骤
当mid和K在同一区域的时候,比如mid和K都在左区域,num[mid] > num[K],那么对left到mid – 1的区域做对K做一般的二分查找,这样就能得到最终的结果,如果num[mid] < num[K],设left = mid,重新回到判断mid和K在哪个区域的步骤(1)
当mid和K在不同区域的时候,比如mid在左区域,K在右区域,这个时候num[K]<num[mid]一定成立,设left = mid,重新进入步骤(1)
终止条件是left = right -1,这个时候left指向左区域最右端的点,right指向右区域最左端的点,这个时候直接判断K和num[left]和num[right]是否相等就好了,不相等返回-1
#include<iostream>
using namespace std;
int secondFind(int num[], int left, int right, int K)
{
int mid;
while (left <= right)
{
mid = (left + right) / 2;
if (K == num[mid]) return mid;
if (K > num[mid])
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
return -1;
}
int theMainFind(int num[], int left, int right, int K)
{
while (right != left + 1)
{
int mid = (left + right) / 2;
if (K == num[mid]) return mid;
if (K == num[left]) return left;
if (K == num[right]) return right;
if ((K == num[left] && K == num[right])||(num[mid] == num[left] && num[mid] == num[right]))
{
for (int i = left; i <= right; i++)
{
if (num[i] == K) return i;
}
return -1;
}
else
{
if (K > num[left])
{
if (num[mid] > num[left])
{
if (K > num[mid])
{
left = mid;
}
else
{
return secondFind(num, left, mid - 1, K);
}
}
else
{
right = mid;
}
}
else
{
if (num[mid] < num[right])
{
if (K < num[mid])
{
right = mid;
}
else
{
return secondFind(num, mid + 1, right, K);
}
}
else
{
left = mid;
}
}
}
}
if (num[left] == K) return left;
if (num[right] == K) return right;
return -1;
}
int main()
{
int N = 6;
int K = 5;
int num[] = {4,5, 6, 1, 2, 3 };
int left = 0;
int right = N - 1;
cout<<theMainFind(num, left, right, K);
return 0;
}