经典算法 | 在旋转数组中查找数字K最优化方法

题目:把一个一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,给定一个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;

}

猜你喜欢

转载自blog.csdn.net/u012737193/article/details/82683529