Data structures 在旋转排序数组中搜索数字

Data structures 在旋转排序数组中搜索数字,data-structures,Data Structures,给定一个可旋转的排序数组,以最小的时间复杂度查找其中的元素 例如:数组内容可以是[8,1,2,3,4,5]。假设您在其中搜索8。O(log(N)) 归结为查找最大数位置的问题,这可以通过检查区域的第一个、最后一个和中间数来完成,递归地缩小区域,进行分治,这是O(log(N))不大于二进制搜索O(log(N)) 编辑: 例如,你有 6 7 8 1 2 3 4 5 ^ ^ ^ 通过查看3个数字,您知道最小/最大数字(稍后将称为mark)的位置在67812区域,因此3 44

给定一个可旋转的排序数组,以最小的时间复杂度查找其中的元素

例如:数组内容可以是[8,1,2,3,4,5]。假设您在其中搜索8。

O(log(N))

归结为查找最大数位置的问题,这可以通过检查区域的第一个、最后一个和中间数来完成,递归地缩小区域,进行分治,这是O(log(N))不大于二进制搜索O(log(N))

编辑: 例如,你有

6 7 8 1 2 3 4 5  
^       ^     ^ 
通过查看3个数字,您知道最小/最大数字(稍后将称为mark)的位置在67812区域,因此3 445是不考虑的(通常通过移动指向数字6和2的区域开始/结束索引(int)来完成)

下一步,

6 7 8 1 2  
^   ^   ^  
再次,您将获得足够的信息来判断标记在哪一侧(左侧或右侧),然后该区域再次减少到一半(6 7 8)

这就是想法:我认为你可以改进一个更好的版本,实际上,对于面试来说,一个带有干净代码的OK算法比一个带有OK代码的最佳算法要好:你最好手拿一些来加热


祝你好运

解决方案仍然是二进制搜索,即需要将数组分成两部分进行检查

在排序数组中,只需查看每个部分,确定元素是位于第一部分(我们称之为a)还是第二部分(B)。因为,根据排序数组的定义,分区a和分区B将被排序,这只需要对分区边界和搜索键进行一些简单的比较

在旋转排序数组中,只能保证对a和B中的一个进行排序。如果元素位于已排序的零件中,那么解决方案很简单:只需像执行普通二进制搜索一样执行搜索。但是,如果必须搜索未排序的部分,则只需递归调用未排序部分的搜索函数即可

这最终导致时间复杂度为
O(lgn)

(实际上,我认为这样一个数据结构将有一个索引伴随它,以指示阵列已旋转了多少个位置。)

编辑:在谷歌上搜索,我看到了CodeGuru上讨论同一问题的有点过时(但正确)的主题。为了补充我的答案,我将复制这里给出的一些伪代码,以便它与我的解决方案一起出现在这里(思路如下所示):


我最近在一次采访中被问到这个问题。这个问题是描述一种在循环排序数组中搜索“键”的算法。我还被要求编写相同的代码。 这就是我想到的:

使用分治二进制搜索。 对于每个子阵列,检查阵列是否已排序。如果已排序,请使用经典二进制搜索 e、 g

data[start]
    public boolean search(int start,int end){
    int mid =(start+end)/2;
    if(start>end)
    {
        return  false;
    }
    if(data[start]<data[end]){
        return this.normalBinarySearch(start, end);
    }
    else{
        //the other part is unsorted.
        return (this.search(start,mid) ||
        this.search(mid+1,end));
    }
}
公共布尔搜索(int开始,int结束){
int mid=(开始+结束)/2;
如果(开始>结束)
{
返回false;
}

如果(数据[开始],以下是我的方法:

public static int findMin(int[] a, int start, int end){
  int mid = (start + end)/2;
  if(start == mid){
    return a[mid+1];
  }else if(a[start] > a[mid]){
    return findMin(a, start, mid);
  }else if(a[mid+1] > a[start]){
    return findMin(a, mid+1, end);
  }else{
    return a[mid+1];
  }
}

时间复杂度:O(logn)

在任何索引处,一个分区将被排序,另一个分区将被未排序。如果键位于已排序分区内,则在已排序数组中搜索,否则在未排序分区中搜索

BS(lo, hi)
m = (lo + hi)/2
if(k = a[m])
    return m
b = 0
if(a[hi] > a[m])
    b = 1
if(b)
    if(k > a[m] && k<a[hi])
        BS(m+1, hi)
else
    BS(lo, m-1)
BS(低、高)
m=(低+高)/2
如果(k=a[m])
返回m
b=0
如果(a[hi]>a[m])
b=1
如果(b)
如果(k>a[m]&&k
#包括
使用名称空间std;
int二进制搜索(int*a,int键,int长度)
{
int l=0,r=length-1,res=-1;

while(la[mid]&&key a[r]&&!(key>=a[l]&&key//此解决方案使用递归将数组划分为两个相等的子数组,并对单个已排序数组应用二进制搜索,然后继续划分未排序的数组

public class SearchRotatedSortedArray
{
    public static void main(String... args)
    {
        int[] array={5,6,1,2,3,4};

        System.out.println(search(array,Integer.parseInt(args[0]),0,5));
    }

    public static boolean search(int[] array,int element,int start,int end)
    {   
    if(start>=end)
    {
        if (array[end]==element) return true;else return false;
    }

    int mid=(start+end)/2;
    if(array[start]<array[end])
    {
        return binarySearch(array,element,start,end);
    }

    return search(array,element,start,mid)||search(array,element,mid+1,end);    
}

    public static boolean binarySearch(int[] array,int element,int start,int end)
    {
        int mid;

        while(start<=end)
        {
            mid=(start+end)/2;

            if(array[mid]==element)
            return true;

            if(array[mid]<element)
            {
                start=mid+1;

            }
            else
            {
                end=mid-1;

            }
        }

        return false;
    }
}
公共类SearchRotatedSortedDarray
{
公共静态void main(字符串…参数)
{
int[]数组={5,6,1,2,3,4};
System.out.println(搜索(数组,Integer.parseInt(args[0]),0,5));
}
公共静态布尔搜索(int[]数组、int元素、int开始、int结束)
{   
如果(开始>=结束)
{
if(array[end]==element)返回true;else返回false;
}
int mid=(开始+结束)/2;
if(数组[start]
int findIndexInRotatedSort(向量输入,int s,int e,int toFind)
{
如果(s>e | | s>=input.size()| | e<0)
{
返回-1;
}
int m=(s+e)/2;
int sVal=输入。在(s)处;
int eVal=输入。在(e)处;
int mVal=输入。在(m)处;
if(sVal==toFind)
返回s;
如果(eVal==toFind)
返回e;
if(mVal==toFind)
返回m;
bool isFirstOrdered=(sValmVal)
{
如果(!IsSecondOred | | toFindsVal)
{
返回findIndexInRotatedSort(输入,s,m-1,toFind);
}
其他的
{
返回findIndexInRotatedSort(输入,m+1,e,toFind);
}
}
}

您可以使用仅公开的类包装数组

E-get(int-index)

并将表现为常规排序数组。 对于ex,如果您有451234,wrapper.get(0)将返回1

现在您可以重用二进制搜索解决方案

包装器可以如下所示:

class RotatedArrayWrapper<T> {
  int startIndex;
  private final List<T> rotatedArray;

  public RotatedArrayWrapper(List<T> rotatedArray) {
    this.rotatedArray = rotatedArray;
    //find index of the smalest element in array
    //keep in mind that there might be duplicates
    startIndex = ... 
  } 

  public T get(int index) {
    int size = rotatedArray.size();
    if (index > size) throw Exception...

    int actualIndex = (startIndex + index) % size;
    return rotatedArray.get(actualIndex);
  }
}
class RotatedArrayWrapper{
国际标准指数;
私人最终名单轮换阵列;
公共旋转阵列振打器(列表旋转阵列){
this.rotatedArray=rotatedArray;
//查找索引
public class SearchRotatedSortedArray
{
    public static void main(String... args)
    {
        int[] array={5,6,1,2,3,4};

        System.out.println(search(array,Integer.parseInt(args[0]),0,5));
    }

    public static boolean search(int[] array,int element,int start,int end)
    {   
    if(start>=end)
    {
        if (array[end]==element) return true;else return false;
    }

    int mid=(start+end)/2;
    if(array[start]<array[end])
    {
        return binarySearch(array,element,start,end);
    }

    return search(array,element,start,mid)||search(array,element,mid+1,end);    
}

    public static boolean binarySearch(int[] array,int element,int start,int end)
    {
        int mid;

        while(start<=end)
        {
            mid=(start+end)/2;

            if(array[mid]==element)
            return true;

            if(array[mid]<element)
            {
                start=mid+1;

            }
            else
            {
                end=mid-1;

            }
        }

        return false;
    }
}
int findIndexInRotatedSort( vector<int> input, int s, int e, int toFind )
    {
        if (s > e || s >= input.size() || e < 0)
        {
            return -1;
        }

        int m = (s + e)/2;

        int sVal = input.at(s);
        int eVal = input.at(e);
        int mVal = input.at(m);

        if (sVal == toFind)
            return s;
        if (eVal == toFind)
            return e;
        if (mVal == toFind)
            return m;

        bool isFirstOrdered = (sVal < mVal);
        bool isSecondOrdered = (mVal < eVal);
        if (toFind > mVal)
        {
            if (!isSecondOrdered || toFind < eVal)
            {
                return findIndexInRotatedSort( input, m+1, e, toFind );
            }
            else
            {
                return findIndexInRotatedSort( input, s, m-1, toFind );
            }
        }
        else
        {
            if (!isFirstOrdered || toFind > sVal)
            {
                return findIndexInRotatedSort( input, s, m-1, toFind );
            }
            else
            {
                return findIndexInRotatedSort(  input, m+1, e, toFind );
            }
        }
    }
class RotatedArrayWrapper<T> {
  int startIndex;
  private final List<T> rotatedArray;

  public RotatedArrayWrapper(List<T> rotatedArray) {
    this.rotatedArray = rotatedArray;
    //find index of the smalest element in array
    //keep in mind that there might be duplicates
    startIndex = ... 
  } 

  public T get(int index) {
    int size = rotatedArray.size();
    if (index > size) throw Exception...

    int actualIndex = (startIndex + index) % size;
    return rotatedArray.get(actualIndex);
  }
}
from bisect import bisect_left


def index(a, x):
    """Binary search to locate the leftmost value exactly equal to x.
    see http://docs.python.org/2/library/bisect.html#searching-sorted-lists

    >>> index([5, 14, 27, 40, 51, 70], 27)
    2
    >>> index([1, 2, 3, 4], 10)
    Traceback (most recent call last):
        ...
    ValueError
    """
    i = bisect_left(a, x)
    if i != len(a) and a[i] == x:
        return i
    raise ValueError


def _index_shifted(value, sequence, start, stop):
    """Recursive reset location and binary search"""
    # if at reset (min) and it's not the value, it's not there
    if start == stop and sequence[start] != value:
        return -1
    mid = (stop + start) // 2
    # check mid, since we are already here
    if sequence[mid] == value:
        return mid
    # right side is sorted
    elif sequence[mid] < sequence[stop]:
        # if value falls in range, search righ
        if sequence[stop] >= value > sequence[mid]:
            return index(sequence[mid:stop + 1], value) + mid
        # partition left side
        return _index_shifted(value, sequence, start, mid)
    # left side is sorted
    else:
        # if value falls in range, search left
        if sequence[mid] > value >= sequence[start]:
            return index(sequence[start:mid], value) + start
        # partition right side
        return _index_shifted(value, sequence, mid + 1, stop)


def index_shifted(sequence, value):
    """Returns index of value in a shifted sorted sequence; -1 if not present.

    >>> index_shifted([10, 13, 16, 19, 22, 25, 28, 31, 34, 37], 10)
    0
    >>> index_shifted([10, 13, 16, 19, 22, 25, 28, 31, 34, 37], 37)
    9
    >>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 10)
    2
    >>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 37)
    1
    >>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 13)
    3
    >>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 25)
    7
    >>> index_shifted([25, 28, 31, 34, 37, 10, 13, 16, 19, 22], 10)
    5
    >>> index_shifted([25, 28, 31, 34, 37, 10, 13, 16, 19, 22], -10)
    -1
    >>> index_shifted([25, 28, 31, 34, 37, 10, 13, 16, 19, 22], 100)
    -1
    """
    return _index_shifted(value, sequence, 0, len(sequence) - 1)
public class RoatatedSorted {

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub

    int[] rotArray = {5,6,7,8,9,10,15,16,17,1,2,3,4,};

    search(rotArray,0,rotArray.length-1,10);

}

private static void search(int[] a, int low, int high,int key) {

    //int mid =  low + (high-low)/2;
    //if(a[mid]==a[key]){System.out.println("element found at" + key+1 +" position"); return;}

    // find pos to split array
    int pos = findSplitIndex(a,low,high);
    System.out.println("split pos found at" + pos +" position");


    if(key>=a[low]&& key <=a[pos])
        bsearch(a,low,pos,key);
    if(key>=a[pos+1]&& key <=a[high])
        bsearch(a,pos+1,high,key);  
}


private static void bsearch(int[] a, int low, int high,int key) {
    // TODO Auto-generated method stub
    if(low>high) return;
    int mid =  low + (high-low)/2;
    if(a[mid]==key)
    {System.out.println("element found at" + ++mid +" position"); return;}
    if(a[mid] > key)
        bsearch(a,low,mid-1,key);
    if(a[mid]<key)
        bsearch(a,mid+1,high,key);
}

private static int findSplitIndex(int[] a, int low, int high) {
    // TODO Auto-generated method stub
    int mid;
    if(low>high)return -1;
    while(true) {
        mid =  low + (high-low)/2;
    if( a[mid]>a[mid+1])
    break;


    if(a[mid]>a[low])
        low=mid;
    if(a[high]>a[mid])
        high=mid;
}
    return mid;


}

}
//Search an element in a sorted and pivoted array
    class SearchInPivotedSortedArray
    {
        //searchInOrtedPivotedArray : Return index of matched element with given value.
        public static int searchInSortedPivotedArray(int[] A, int value)
        {
            int min = findMinElement(A,0,A.Length-1);
            if (min == A[0])
               return binarySearchTree(A, 0, A.Length-1, value);


            if (value <= A[A.Length-1])
               return binarySearchTree(A, min, A.Length-1, value);
            else
               return binarySearchTree(A, 0, min-1, value);


        }
        //return index of Pivot element
        public static int findMinElement(int[] Array, int low, int high)
        {

            if (low >= high)
                return low;

            int mid = (low + high) / 2;
            if (mid > low && Array[mid] < Array[mid - 1])
                return mid;
            if (mid < high && Array[mid] > Array[mid + 1])
                return mid + 1;

            if (Array[mid] < Array[high])
                return findMinElement(Array, low, mid - 1);

            return findMinElement(Array, mid + 1, high);

        }
        //Return match element index, if not found return -1
        public static int binarySearchTree(int[] array, int low, int high,int value)
        {
            if (low > high)
                return -1;
            int mid = (low + high)/2;

            if (array[mid] == value)
                return mid;
            if (array[mid] > value)
                return binarySearchTree(array, low, mid - 1, value);
            else
                return binarySearchTree(array, mid + 1, high, value);

        }
    }
Example : [6,7,8,1,2,3,5]

int findElementIndex(int []a, int element, int start, int end)
{
    int mid = (start + end)>>1;

    if(start>end)
        return -1;

    if(a[mid] == element)
    return mid;

    if(a[mid] < a[start])
    {
       if(element <= a[end] && element > a[mid])
        {
       return findElementIndex(a,element,mid+1,end);
        }
        else{
       return findElementIndex(a,element,start,mid-1);
        }
     }
    else  if(a[mid] > a[start]){
        if(element >= a[start] && element < a[mid])
             return findElementIndex(a,element,start,mid-1);
        else
            return findElementIndex(a,element,mid+1,end);
    }
    else if (a[mid] == a[start]){
        if(a[mid] != a[end]) // repeated elements
          return findElementIndex(a,element,mid+1,end);
        else
            int left = findElementIndex(a,element,start,mid-1);
            int right = findElementIndex(a,element,mid+1,end);

            return (left != -1) ? left : right;

    }

}
public static int rbs(int[] a, int l, int r, int t) {

    if (a[l] <= a[r]) {
        return bs(a, l, r, t);
    }

    if (r < l) {
        return -1;
    } else {
        int m = (l+r) / 2;
        if (a[m] == t) {
            return m;
        } else if (a[m] > t) { // check left half
            if (a[l] > a[m]) { // left is unsorted
                return rbs(a, l, m-1, t);
            } else { // left is sorted
                if (a[l] < t) { // t is in range
                    return bs(a, l, m-1, t);
                } else if (a[l] > t) { // t is out of range on left
                    if (a[r] >= t) {
                        return rbs (a, m+1, r, t);
                    } else
                        return -1;
                } else
                    return l;
            }
        } else { // other side
            if (a[r] < a[m]) { // right is unsorted
                return rbs(a, m+1, r, t);
            } else { // right is sorted
                if (a[r] > t) { // t is in range
                    return bs(a, m+1, r, t);
                } else if (a[r] < t) { // t is out of range on right side
                    if (a[l] <= t) {
                        return rbs (a, l, m-1, t);
                    } else
                        return -1;
                } else
                    return r;
            }
        }
    }
}


public static int bs(int[] a, int l, int r, int t) {

    int m = (l+r) / 2;

    if (r < l) {
        return -1;
    } else {
        if (a[m] == t)
            return m;
        else if (a[m] < t)
            return bs(a, m+1, r, t);
        else
            return bs (a, l, m-1, t);
    }
}
     public static int findElement(int[] a, int key, int left, int right) {

           if (left > right) {
              return -1;
           }

           int mid = (left + right) / 2;

           if (key == a[mid]) {
              return mid;
           } else if (key < a[mid]) {
              return (a[left] <= a[mid] && a[left] < key ? findElement(
                a, key, left, mid - 1) : findElement(a, key,
                mid + 1, right));
           } else {
              return (a[mid] <= a[right] && a[right] < key ? findElement(
                a, key, left, mid - 1) : findElement(a, key,
                mid + 1, right));
    }

}
int search(int A[], int s, int e, int k) {
    if (s <= e) {
        int m = s + (e - s)/2;
        if (A[m] == k)
            return m;
        if (A[m] < A[e] && k > A[m] && k <= A[e]) 
            return search(A, m+1, e, k);
        if (A[m] > A[s] && k < A[m] && k >= A[s]) 
            return search(A, s, m-1, k);
        if (A[m] < A[s]) 
            return search(A, s, m-1, k);
        if (A[m] > A[e])
            return search(A, m+1, e, k);
    }
    return -1;
}
@implementation BinarySearcher

- (BOOL)isValue:(int)value inArray:(int[])array withArraySize:(int)size {

    return [self subSearchArray:array forValue:value fromIndex:0 toIndex:size -1];
}

- (BOOL)subSearchArray:(int[])array forValue:(int)value fromIndex:(int)left toIndex:(int)right {

    if (left <= right) {

        int middle = (left + right) / 2;

        BOOL leftArraySorted = array[left] <= array[middle];
        BOOL rightArraySorted = array[middle + 1] <= array[right];

        if (array[middle] == value) {
            return YES;
        } else if (leftArraySorted && value >= array[left] && value < array[middle]) {
            return [self subSearchArray:array forValue:value fromIndex:left toIndex:middle];
        } else if (rightArraySorted && value >= array[middle + 1] && value <= array[right]) {
            return [self subSearchArray:array forValue:value fromIndex:middle + 1 toIndex:right];
        } else if (!leftArraySorted) {
            return [self subSearchArray:array forValue:value fromIndex:left toIndex:middle];
        } else if (!rightArraySorted) {
            return [self subSearchArray:array forValue:value fromIndex:middle + 1 toIndex:right];
        }
    }

    return NO;
}

@end
def findNumber(a, x, start, end):
  if start > end:
    return  -1
  mid = (start + end) / 2
  if a[mid] == x:
    return mid
  ## Case : 1  if a[start] to a[mid] is sorted , then search first half of array
  if a[start] < a[mid]:
    if (x >= a[start] and x <= a[mid]):
      return findNumber(a, x, start, mid - 1)
    else:
      return findNumber(a,x, mid + 1, end)
  ## Case: 2 if a[start] to a[mid] is not sorted , then a[mid] to a[end] mist be sorted
  else:
    if (x >= a[mid] and x <= a[end]):
      return findNumber(a, x, mid + 1, end)
    else:
      return findNumber(a,x, start, mid -1)


a = [4,5,6,7,0,1,2]
print "Your array is  : " , a
x = input("Enter any number to find in array : ")
result = findNumber(a, x, 0, len(a) - 1)
print "The element is present at %d position: ", result
    # Check if middle element is same as the target.
    mid = (left + right) / 2
    if array[mid] == target:
        return mid

    # Pivot point is at the right of the middle element.
    if array[left] <= array[mid]:
        if target >= array[left] and target <= array[mid]:
            return search(array, left, mid - 1, target)
        return search(array, mid + 1, right, target)

    # Pivot point is at the left of the middle element.
    if target >= array[mid] and target <= array[right]:
        return search(array, mid + 1, right, target)
    return search(array, left, mid - 1, target)
public static int SearchRotatedSortedArray(int l, int d, int[] array, int toFind) {
    if (l >= d) {
        return -1;
    }
    if (array[l] == toFind) {
        return l;
    }
    if (array[d] == toFind) {
        return d;
    }

    int mid = (l + d) / 2;
    if (array[mid] == toFind) {
        return mid;
    }

    if ((array[mid] > toFind && toFind > array[l]) || (array[mid] < toFind && array[d] < toFind)) {
        return SearchRotatedSortedArray(l, mid - 1, array, toFind);
    } else {
        return SearchRotatedSortedArray(mid + 1, d, array, toFind);
    }

}