【问题标题】:Searching in a sorted and rotated array在排序和旋转的数组中搜索
【发布时间】:2011-06-14 00:20:24
【问题描述】:

在准备面试时,我偶然发现了一个有趣的问题:

你得到了一个经过排序然后旋转的数组。

例如:

  • arr = [1,2,3,4,5],这是排序的
  • 向右旋转两次以提供 [4,5,1,2,3]

现在如何最好地在这个排序 + 旋转的数组中进行搜索?

可以取消旋转数组,然后进行二分搜索。但这并不比在输入数组中进行线性搜索更好,因为两者都是最坏情况 O(N)。

请提供一些指示。我在谷歌上搜索了很多关于此的特殊算法,但找不到。

我了解 C 和 C++。

【问题讨论】:

  • 如果这是作业,请添加homework标签。这会鼓励人们温和地推动你朝着正确的方向前进,而不是发布可粘贴的答案。
  • 你知道数组旋转了多少次吗?
  • 对于这么大的数组,完全不用担心。你真正的问题是什么?
  • 不,这不是家庭作业。我不知道旋转的次数。这个例子很简单。数组可以有数百万个元素。
  • 数组是否总是有从 1 开始的连续值?或者它可以有任何东西(包括重复)?

标签: c++ c arrays algorithm


【解决方案1】:

这可以在O(logN) 中使用稍微修改的二分搜索来完成。

排序+旋转数组的有趣特性是,当您将其分成两半时,两半中至少有一个将始终被排序。

Let input array arr = [4,5,6,7,8,9,1,2,3]
number of elements  = 9
mid index = (0+8)/2 = 4

[4,5,6,7,8,9,1,2,3]
         ^
 left   mid  right

似乎右子数组未排序,而左子数组已排序。

如果 mid 恰好是旋转点,它们左右子数组都将被排序。

[6,7,8,9,1,2,3,4,5]
         ^

但在任何情况下,一半(子数组)都必须排序

通过比较每一半的开始和结束元素,我们可以很容易地知道哪一半是排序的。

一旦我们找到哪一半已排序,我们就可以查看关键是否存在于那一半中 - 与极端情况进行简单比较。

如果密钥存在于那一半,我们递归地调用那一半的函数
否则我们递归调用另一半的搜索。

我们在每次调用中丢弃数组的一半,这使得该算法O(logN)

伪代码:

function search( arr[], key, low, high)

        mid = (low + high) / 2

        // key not present
        if(low > high)
                return -1

        // key found
        if(arr[mid] == key)
                return mid

        // if left half is sorted.
        if(arr[low] <= arr[mid])

                // if key is present in left half.
                if (arr[low] <= key && arr[mid] >= key) 
                        return search(arr,key,low,mid-1)

                // if key is not present in left half..search right half.
                else                 
                        return search(arr,key,mid+1,high)
                end-if

        // if right half is sorted. 
        else    
                // if key is present in right half.
                if(arr[mid] <= key && arr[high] >= key) 
                        return search(arr,key,mid+1,high)

                // if key is not present in right half..search in left half.
                else
                        return search(arr,key,low,mid-1)
                end-if
        end-if  

end-function

这里的关键是一个子数组总是被排序的,使用它我们可以丢弃一半的数组。

【讨论】:

  • 简单。简洁的。例子。 FTW !!
  • 解决方案中应该有哪些变化来容纳重复项,因为这不适用于具有重复项的数组,例如在 {10, 15, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10} 中搜索“15”?
  • “排序+旋转数组的有趣特性是,当你将它分成两半时,两半中至少有一个总是被排序的。”这将天才或有经验的人与新手区分开来。谢谢,这一行帮助我可视化了整个解决方案。
  • 这是我能找到的关于这个问题的最佳解释。
  • [1, 3] 如果我试图找到 3 则输出不正确
【解决方案2】:

当数组中有重复元素时,接受的答案有一个错误。例如,arr = {2,3,2,2,2} 和 3 就是我们要查找的内容。然后接受答案中的程序将返回 -1 而不是 1。

《Cracking the Coding Interview》一书中详细讨论了这个面试问题。该书专门讨论了重复元素的情况。由于操作在评论中说数组元素可以是任何东西,我将我的解决方案作为伪代码提供如下:

function search( arr[], key, low, high)

    if(low > high)
        return -1
    
    mid = (low + high) / 2
    
    if(arr[mid] == key)
        return mid

    // if the left half is sorted.
    if(arr[low] < arr[mid]) {

        // if key is in the left half
        if (arr[low] <= key && key <= arr[mid]) 
            // search the left half
            return search(arr,key,low,mid-1)
        else
            // search the right half                 
            return search(arr,key,mid+1,high)
        end-if

    // if the right half is sorted. 
    else if(arr[mid] < arr[high])    
        // if the key is in the right half.
        if(arr[mid] <= key && arr[high] >= key) 
            return search(arr,key,mid+1,high)
        else
            return search(arr,key,low,mid-1)
        end-if
   
    else if(arr[mid] == arr[low])
       
        if(arr[mid] != arr[high])
            // Then elements in left half must be identical. 
            // Because if not, then it's impossible to have either arr[mid] < arr[high] or arr[mid] > arr[high]
            // Then we only need to search the right half.
            return search(arr, mid+1, high, key)
        else 
            // arr[low] = arr[mid] = arr[high], we have to search both halves.
            result = search(arr, low, mid-1, key)
            if(result == -1)
                return search(arr, mid+1, high, key)
            else
                return result
   end-if
end-function

【讨论】:

  • 我认为你是唯一一个正确考虑重复元素的人。但是您的方法不能保证对数复杂度。尤其是在输入,例如 5,5,5,5,5,5, ...(大量修复),5,1, 5
  • 如果我们有重复的元素,时间复杂度是多少?
  • 我认为如果允许重复,它必须是线性的。考虑一个包含 N 个1s 的列表,其中一个2 在某处。它可以在任何地方,并且将是有效的输入。我们正在寻找2。无论我们考虑什么范围的 M>2 数字,如果2 不在任何一边,我们都无法判断它是否包含在这些 M 数字中。因此,您不能以任何有帮助的方式缩小搜索范围。
【解决方案3】:

您可以进行 2 次二进制搜索:首先找到索引 i 使得 arr[i] &gt; arr[i+1]

显然,(arr\[1], arr[2], ..., arr[i])(arr[i+1], arr[i+2], ..., arr[n]) 都是有序数组。

如果arr[1] &lt;= x &lt;= arr[i],则在第一个数组进行二进制搜索,否则在第二个数组。

复杂度O(logN)

编辑: the code.

【讨论】:

  • 谢谢 max 但我不明白你将如何申请你的第一个学士学位?
  • 我的意思是你的搜索关键字是什么?
  • @Jones,写代码比解释更容易。我编辑了答案,寻找链接。
  • 为什么必须明确搜索“断点”?为什么不直接使用修改后的二进制搜索来搜索元素并同时检查“异常”?
  • 我来晚了,我被问到同样的问题,我没有在 O(logn) 中解决它,我的解决方案对 O(n) 的改进不大。我的方法是两个指针 i = 0 和 j = size() - 1,在循环中检查 arr[i] == key 或 arr[j] == key if found return i or j and break, else icrement i and decrement j ,中断条件是 i
【解决方案4】:

我的第一次尝试是使用二进制搜索来查找应用的旋转次数 - 这可以通过使用通常的二进制搜索机制找到索引 n 其中 a[n] > a[n + 1] 来完成。 然后在找到的每个班次旋转所有索引的同时进行常规二进制搜索。

【讨论】:

  • 在做 BS 查找 rot 数时,您的搜索关键字是什么?
  • @Jones:这将是一个修改后的二分搜索。您正在寻找两个相邻值减小的点。猜一个索引。如果该索引处的值大于数组中的第一个值,则继续查看猜测的右侧。如果它更少,请继续向左看。但是,如果您实际上并不关心不连续性的位置,那么 codaddict 的答案会更好,您只想执行搜索。
【解决方案5】:
int rotated_binary_search(int A[], int N, int key) {
  int L = 0;
  int R = N - 1;

  while (L <= R) {
    // Avoid overflow, same as M=(L+R)/2
    int M = L + ((R - L) / 2);
    if (A[M] == key) return M;

    // the bottom half is sorted
    if (A[L] <= A[M]) {
      if (A[L] <= key && key < A[M])
        R = M - 1;
      else
        L = M + 1;
    }
    // the upper half is sorted
    else {
      if (A[M] < key && key <= A[R])
        L = M + 1;
      else
        R = M - 1;
    }
  }
  return -1;
}

【讨论】:

  • 如上所述,这不会处理重复条目的情况。但是,如果元素是唯一的,这是一个非常简单的代码,因为它不进行任何递归。
【解决方案6】:

如果你知道数组已经向右旋转了 s,你可以简单地做一个将 s 向右移动的二分查找。这是 O(lg N)

我的意思是,将左极限初始化为 s,将右极限初始化为 (s-1) mod N,并在它们之间进行二分搜索,注意在正确的区域工作。

如果不知道数组旋转了多少,可以用二分查找确定旋转的大小,即O(lg N),然后做移位二分查找,O(lg N ),总共还是 O(lg N)。

【讨论】:

    【解决方案7】:

    回复上面提到的帖子“这个面试问题在'Cracking the Coding Interview'一书中有详细讨论。重复元素的情况在那本书中专门讨论过。由于op在评论中说数组元素可以什么,我在下面将我的解决方案作为伪代码提供:"

    您的解决方案是 O(n) ! (最后一个 if 条件是您检查数组的两半是否有单个条件,这使它成为线性时间复杂度的溶胶)

    我最好进行线性搜索,而不是在编码回合中陷入错误和分段错误的迷宫。

    我认为没有比 O(n) 更好的解决方案来搜索旋转排序数组(有重复项)

    【讨论】:

      【解决方案8】:

      如果您知道它旋转了多远(多远),您仍然可以进行二分搜索。

      诀窍是你得到两个级别的索引:你做 b.s.在虚拟 0..n-1 范围内,然后在实际查找值时不旋转它们。

      【讨论】:

        【解决方案9】:

        您不需要先旋转阵列。您可以对旋转后的数组使用二分搜索(进行一些修改)。

        让 N 是您要搜索的数字:

        读取第一个数字(arr[start])和数组中间的数字(arr[end]):

        • if arr[start] > arr[end] --> 前半部分未排序,后半部分已排序:

          • if arr[end] > N --> 数字在索引中:(middle + N - arr[end])

          • 如果 N 在数组的第一部分重复搜索(请参阅 end 是数组前半部分的中间等)

        (如果第一部分已排序但第二部分未排序,则相同)

        【讨论】:

          【解决方案10】:
          public class PivotedArray {
          
          //56784321 first increasing than decreasing
          public static void main(String[] args) {
              // TODO Auto-generated method stub
              int [] data ={5,6,7,8,4,3,2,1,0,-1,-2};
          
              System.out.println(findNumber(data, 0, data.length-1,-2));
          
          }
          
          static int findNumber(int data[], int start, int end,int numberToFind){
          
              if(data[start] == numberToFind){
                  return start;
              }
          
              if(data[end] == numberToFind){
                  return end;
              }
              int mid = (start+end)/2;
              if(data[mid] == numberToFind){
                  return mid;
              }
              int idx = -1;
              int midData = data[mid];
              if(numberToFind < midData){
                  if(midData > data[mid+1]){
                      idx=findNumber(data, mid+1, end, numberToFind);
                  }else{
                      idx =  findNumber(data, start, mid-1, numberToFind);
                  }
              }
          
              if(numberToFind > midData){
                  if(midData > data[mid+1]){
                      idx =  findNumber(data, start, mid-1, numberToFind);
          
                  }else{
                      idx=findNumber(data, mid+1, end, numberToFind);
                  }
              }
              return idx;
          }
          
          }
          

          【讨论】:

            【解决方案11】:
            short mod_binary_search( int m, int *arr, short start, short end)
            {
            
             if(start <= end)
             {
                short mid = (start+end)/2;
            
                if( m == arr[mid])
                    return mid;
                else
                {
                    //First half is sorted
                    if(arr[start] <= arr[mid])
                    {
                        if(m < arr[mid] && m >= arr[start])
                            return mod_binary_search( m, arr, start, mid-1);
                        return mod_binary_search( m, arr, mid+1, end);
                    }
            
                    //Second half is sorted
                    else
                    {
                        if(m > arr[mid] && m < arr[start])
                            return mod_binary_search( m, arr, mid+1, end);
                        return mod_binary_search( m, arr, start, mid-1);
                    }
                }
             }
             return -1;
            }
            

            【讨论】:

              【解决方案12】:

              首先,您需要找到位移常数 k。 这可以在 O(lgN) 时间内完成。 从常数移位 k 中,您可以轻松找到要使用的元素 常数 k 的二分查找。增强二分搜索也需要 O(lgN) 时间 总运行时间为 O(lgN + lgN) = O(lgN)

              要找到常数位移,k。您只需要在数组中查找最小值。数组最小值的索引告诉你常量移位。 考虑排序数组 [1,2,3,4,5]。

              可能的转变是: [1,2,3,4,5] // k = 0 [5,1,2,3,4] // k = 1 [4,5,1,2,3] // k = 2 [3,4,5,1,2] // k = 3 [2,3,4,5,1] // k = 4 [1,2,3,4,5] // k = 5%5 = 0

              要在 O(lgN) 时间内完成任何算法,关键是始终想办法将问题分成两半。 一旦这样做了,其余的实现细节就很容易了

              以下是该算法的 C++ 代码

              // This implementation takes O(logN) time
              // This function returns the amount of shift of the sorted array, which is
              // equivalent to the index of the minimum element of the shifted sorted array. 
              #include <vector> 
              #include <iostream> 
              using namespace std; 
              
              int binarySearchFindK(vector<int>& nums, int begin, int end)
              {
                  int mid = ((end + begin)/2); 
                  // Base cases
                  if((mid > begin && nums[mid] < nums[mid-1]) || (mid == begin && nums[mid] <= nums[end]))     
                      return mid; 
                  // General case 
                  if (nums[mid] > nums[end]) 
                  {
                      begin = mid+1; 
                      return binarySearchFindK(nums, begin, end); 
                  }
                  else
                  {
                      end = mid -1; 
                      return binarySearchFindK(nums, begin, end); 
                  }   
              }  
              int getPivot(vector<int>& nums)
              {
                  if( nums.size() == 0) return -1; 
                  int result = binarySearchFindK(nums, 0, nums.size()-1); 
                  return result; 
              }
              
              // Once you execute the above, you will know the shift k, 
              // you can easily search for the element you need implementing the bottom 
              
              int binarySearchSearch(vector<int>& nums, int begin, int end, int target, int pivot)
              {
                  if (begin > end) return -1; 
                  int mid = (begin+end)/2;
                  int n = nums.size();  
                  if (n <= 0) return -1; 
              
                  while(begin <= end)
                  {
                      mid = (begin+end)/2; 
                      int midFix = (mid+pivot) % n; 
                      if(nums[midFix] == target) 
                      {
                          return midFix; 
                      }
                      else if (nums[midFix] < target)
                      {
                          begin = mid+1; 
                      }
                      else
                      {
                          end = mid - 1; 
                      }
                  }
                  return -1; 
              }
              int search(vector<int>& nums, int target) {
                  int pivot = getPivot(nums); 
                  int begin = 0; 
                  int end = nums.size() - 1; 
                  int result = binarySearchSearch(nums, begin, end, target, pivot); 
                  return result; 
              }
              
              希望这会有所帮助!=) 顺志龙, 多伦多大学

              【讨论】:

                【解决方案13】:

                对于具有重复项的旋转数组,如果需要找到第一次出现的元素,可以使用以下过程(Java 代码):

                public int mBinarySearch(int[] array, int low, int high, int key)
                {
                    if (low > high)
                        return -1; //key not present
                
                    int mid = (low + high)/2;
                
                    if (array[mid] == key)
                        if (mid > 0 && array[mid-1] != key)
                            return mid;
                
                    if (array[low] <= array[mid]) //left half is sorted
                    {
                        if (array[low] <= key && array[mid] >= key)
                            return mBinarySearch(array, low, mid-1, key);
                        else //search right half
                            return mBinarySearch(array, mid+1, high, key);
                    }
                    else //right half is sorted
                    {
                        if (array[mid] <= key && array[high] >= key)
                            return mBinarySearch(array, mid+1, high, key);
                        else
                            return mBinarySearch(array, low, mid-1, key);
                    }       
                
                }
                

                这是对上述 codaddict 程序的改进。注意附加的 if 条件如下:

                if (mid > 0 && array[mid-1] != key)
                

                【讨论】:

                  【解决方案14】:

                  这是一个简单的(时间,空间)效率非递归 O(log n) python 解决方案,它不会修改原始数组。将旋转后的数组切成两半,直到我只有两个索引要检查,如果一个索引匹配则返回正确答案。

                  def findInRotatedArray(array, num):
                  
                  lo,hi = 0, len(array)-1
                  ix = None
                  
                  
                  while True:
                  
                  
                      if hi - lo <= 1:#Im down to two indices to check by now
                          if (array[hi] == num):  ix = hi
                          elif (array[lo] == num): ix = lo
                          else: ix = None
                          break
                  
                      mid = lo + (hi - lo)/2
                      print lo, mid, hi
                  
                      #If top half is sorted and number is in between
                      if array[hi] >= array[mid] and num >= array[mid] and num <= array[hi]:
                          lo = mid
                  
                      #If bottom half is sorted and number is in between
                      elif array[mid] >= array[lo] and num >= array[lo] and num <= array[mid]:
                          hi = mid
                  
                  
                      #If top half is rotated I know I need to keep cutting the array down
                      elif array[hi] <= array[mid]:
                          lo = mid
                  
                      #If bottom half is rotated I know I need to keep cutting down
                      elif array[mid] <= array[lo]:
                          hi = mid
                  
                  print "Index", ix
                  

                  【讨论】:

                    【解决方案15】:

                    试试这个解决方案

                    bool search(int *a, int length, int key)
                    {
                    int pivot( length / 2 ), lewy(0), prawy(length);
                    if (key > a[length - 1] || key < a[0]) return false;
                    while (lewy <= prawy){
                        if (key == a[pivot]) return true;
                        if (key > a[pivot]){
                            lewy = pivot;
                            pivot += (prawy - lewy) / 2 ? (prawy - lewy) / 2:1;}
                        else{
                            prawy = pivot;
                            pivot -= (prawy - lewy) / 2 ? (prawy - lewy) / 2:1;}}
                    return false;
                    }
                    

                    【讨论】:

                      【解决方案16】:

                      C++ 中的这段代码应该适用于所有情况,虽然它适用于重复项,但如果这段代码中存在错误,请告诉我。

                      #include "bits/stdc++.h"
                      using namespace std;
                      int searchOnRotated(vector<int> &arr, int low, int high, int k) {
                      
                          if(low > high)
                              return -1;
                      
                          if(arr[low] <= arr[high]) {
                      
                              int p = lower_bound(arr.begin()+low, arr.begin()+high, k) - arr.begin();
                              if(p == (low-high)+1)
                                  return -1;
                              else
                                  return p; 
                          }
                      
                          int mid = (low+high)/2;
                      
                          if(arr[low] <= arr[mid]) {
                      
                              if(k <= arr[mid] && k >= arr[low])
                                  return searchOnRotated(arr, low, mid, k);
                              else
                                  return searchOnRotated(arr, mid+1, high, k);
                          }
                          else {
                      
                              if(k <= arr[high] && k >= arr[mid+1])
                                  return searchOnRotated(arr, mid+1, high, k);
                              else
                                  return searchOnRotated(arr, low, mid, k);
                          }
                      }
                      int main() {
                      
                          int n, k; cin >> n >> k;
                          vector<int> arr(n);
                          for(int i=0; i<n; i++) cin >> arr[i];
                          int p = searchOnRotated(arr, 0, n-1, k);
                          cout<<p<<"\n";
                          return 0;
                      }
                      

                      【讨论】:

                        【解决方案17】:

                        在 Javascript 中

                        var search = function(nums, target,low,high) {
                            low= (low || low === 0) ? low : 0;
                        
                            high= (high || high == 0) ? high : nums.length -1;
                        
                            if(low > high)
                                return -1;
                        
                            let mid = Math.ceil((low + high) / 2);
                        
                        
                            if(nums[mid] == target)
                                return mid;
                        
                            if(nums[low] < nums[mid]) {
                                // if key is in the left half
                                if (nums[low] <= target && target <= nums[mid]) 
                                    // search the left half
                                    return search(nums,target,low,mid-1);
                                else
                                    // search the right half                 
                                    return search(nums,target,mid+1,high);
                            } else {
                                // if the key is in the right half.
                                if(nums[mid] <= target && nums[high] >= target) 
                                    return search(nums,target,mid+1,high)
                                else
                                    return search(nums,target,low,mid-1)
                            }
                        };
                        

                        输入:nums = [4,5,6,7,0,1,2],目标 = 0 输出:4

                        【讨论】:

                          【解决方案18】:
                          import java.util.*;
                          
                          class Main{
                              public static void main(String args[]){
                                  Scanner sc = new Scanner(System.in);
                                  int n=sc.nextInt();
                                  int arr[]=new int[n];
                                  int max=Integer.MIN_VALUE;
                                  int min=Integer.MAX_VALUE;
                                  int min_index=0,max_index=n;
                          
                                  for(int i=0;i<n;i++){
                                      arr[i]=sc.nextInt();
                                      if(arr[i]>max){
                                          max=arr[i];
                                      max_index=i;
                                      }
                                      if(arr[i]<min){
                                          min=arr[i];
                                          min_index=i;
                                      }
                          
                                  }
                          
                                  int element=sc.nextInt();
                                  int index;
                                  if(element>arr[n-1]){
                                      index=Arrays.binarySearch(arr,0,max_index+1,element);
                                  }
                                  else {
                                       index=Arrays.binarySearch(arr,min_index,n,element);
                                  }
                                  if(index>=0){
                                      System.out.println(index);
                                  }
                                  else{
                                      System.out.println(-1);
                                  }
                              }
                          
                          }
                          

                          【讨论】:

                            【解决方案19】:

                            这是我的两分钱:

                            • 如果数组确实包含重复项,则可以在 O(log(n)) 中找到解决方案。正如许多人所展示的那样,可以使用经过调整的二分搜索来查找目标元素。

                            • 但是,如果数组包含重复项,我认为没有办法在 O(log(n)) 中找到目标元素。这是一个示例,说明了为什么我认为 O(log(n)) 是不可能的。考虑下面的两个数组:

                            a = [2,.....................2...........3,6,2......2]
                            b = [2.........3,6,2........2......................2]
                            

                            所有的点都用数字 2 填充。可以看到两个数组都进行了排序和旋转。如果要考虑二分搜索,那么他们必须在每次迭代中将搜索域减半——这就是我们得到 O(log(n)) 的方式。假设我们正在搜索数字 3。在第一种情况下,我们可以看到它隐藏在数组的右侧,而在第二种情况下,它隐藏在数组的第二面。以下是我们现阶段对数组的了解:

                            • 左 = 0
                            • 右 = 长度 - 1;
                            • 中=左+(右-左)/2;
                            • arr[mid] = 2;
                            • arr[left] = 2;
                            • arr[右] = 2;
                            • 目标 = 3;

                            这就是我们掌握的所有信息。我们可以清楚地看到,仅仅做出排除一半数组的决定是不够的。因此,唯一的方法是进行线性搜索。我并不是说我们不能优化 O(n) 时间,我只是说我们不能做到 O(log(n))。

                            【讨论】:

                              【解决方案20】:

                              由于 mid、mid-1 等,我不喜欢二分搜索,这就是为什么我总是使用 binary stride/jump search

                              如何在旋转数组上使用它? 使用两次(一次查找移位,然后使用 .at() 查找移位索引 -> 原始索引)

                              或者比较第一个元素,如果小于第一个元素,则必须在末尾附近

                              从末端向后跳转搜索,如果找到任何枢轴连杆,则停止

                              如果是 > 开始元素,只需进行正常的跳转搜索 :)

                              【讨论】:

                                【解决方案21】:

                                使用 C# 实现

                                public class Solution {
                                        public int Search(int[] nums, int target) {
                                             if (nums.Length == 0) return -1;
                                                int low = 0;
                                                int high = nums.Length - 1;
                                                while (low <= high)
                                                {
                                                    int mid = (low + high) / 2;
                                                    if (nums[mid] == target) return mid;
                                                    if (nums[low] <= nums[mid]) // 3 4 5 6 0 1 2
                                                    {
                                                        if (target >= nums[low] && target <= nums[mid])
                                                            high = mid;
                                                        else
                                                            low = mid + 1;
                                                    }
                                                    else // 5 6 0 1 2 3 4
                                                    {
                                                        if (target >= nums[mid] && target <= nums[high])
                                                            low= mid;
                                                        else
                                                            high = mid - 1;
                                                    }
                                                }
                                                return -1;
                                        }
                                    }
                                

                                【讨论】:

                                  【解决方案22】:

                                  另一种适用于重复值的方法是找到旋转,然后在我们访问数组时执行常规二进制搜索应用旋转。

                                  test = [3, 4, 5, 1, 2]
                                  test1 = [2, 3, 2, 2, 2]
                                  
                                  def find_rotated(col, num):
                                      pivot = find_pivot(col)
                                      return bin_search(col, 0, len(col), pivot, num)
                                  
                                  def find_pivot(col):
                                      prev = col[-1]
                                      for n, curr in enumerate(col):
                                          if prev > curr:
                                              return n
                                          prev = curr
                                      raise Exception("Col does not seem like rotated array")
                                  
                                  def rotate_index(col, pivot, position):
                                      return (pivot + position) % len(col)
                                  
                                  def bin_search(col, low, high, pivot, num):
                                      if low > high:
                                          return None
                                      mid = (low + high) / 2
                                      rotated_mid = rotate_index(col, pivot, mid)
                                      val = col[rotated_mid]
                                      if (val == num):
                                          return rotated_mid
                                      elif (num > val):
                                          return bin_search(col, mid + 1, high, pivot, num)
                                      else:
                                          return bin_search(col, low, mid - 1,  pivot, num)
                                  
                                  print(find_rotated(test, 2))
                                  print(find_rotated(test, 4))
                                  print(find_rotated(test1, 3))
                                  

                                  【讨论】:

                                    【解决方案23】:

                                    我的简单代码:-

                                    public int search(int[] nums, int target) {
                                        int l = 0;
                                        int r = nums.length-1;
                                        while(l<=r){
                                            int mid = (l+r)>>1;
                                            if(nums[mid]==target){
                                                return mid;
                                            }
                                            if(nums[mid]> nums[r]){
                                                if(target > nums[mid] || nums[r]>= target)l = mid+1;
                                                else r = mid-1;
                                            }
                                            else{
                                                if(target <= nums[r] && target > nums[mid]) l = mid+1;
                                                else r = mid -1;
                                            }
                                        }
                                        return -1;
                                    }
                                    

                                    时间复杂度 O(log(N))。

                                    【讨论】:

                                      【解决方案24】:

                                      问题:在旋转排序数组中搜索

                                      public class SearchingInARotatedSortedARRAY {
                                          public static void main(String[] args) {
                                              int[] a = { 4, 5, 6, 0, 1, 2, 3 };
                                      
                                              System.out.println(search1(a, 6));
                                      
                                          }
                                      
                                          private static int search1(int[] a, int target) {
                                              int start = 0;
                                              int last = a.length - 1;
                                              while (start + 1 < last) {
                                                  int mid = start + (last - start) / 2;
                                      
                                                  if (a[mid] == target)
                                                      return mid;
                                                  // if(a[start] < a[mid]) => Then this part of the array is not rotated
                                                  if (a[start] < a[mid]) {
                                                      if (a[start] <= target && target <= a[mid]) {
                                                          last = mid;
                                                      } else {
                                                          start = mid;
                                                      }
                                                  }
                                                  // this part of the array is rotated
                                                  else {
                                                      if (a[mid] <= target && target <= a[last]) {
                                                          start = mid;
                                                      } else {
                                                          last = mid;
                                                      }
                                                  }
                                              } // while
                                              if (a[start] == target) {
                                                  return start;
                                              }
                                              if (a[last] == target) {
                                                  return last;
                                              }
                                              return -1;
                                          }
                                      }
                                      

                                      【讨论】:

                                        【解决方案25】:

                                        Swift 解决方案 100% 工作测试

                                         func searchInArray(A:[Int],key:Int)->Int{
                                                for i in 0..<A.count{
                                                    if key == A[i] {
                                                        print(i)
                                                        return i
                                                    }
                                                }
                                                print(-1)
                                                return -1
                                            }
                                        

                                        【讨论】:

                                          最近更新 更多