zoukankan      html  css  js  c++  java
  • leetcode第32题--Search in Rotated Sorted Array

    Suppose a sorted array is rotated at some pivot unknown to you beforehand.

    (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

    You are given a target value to search. If found in the array return its index, otherwise return -1.

    You may assume no duplicate exists in the array.

    题目意思是,原先排好序的,然后右移一定位数,在变换后的array中找到给定值改变之后的下标。如果直接扫描一次的话也能Accept,这就失去了出题的意义。题目是想让我们用二分法。在O(logn)的复杂度下实现,而非n复杂度。

    这个人解释的不错如下(先陈述他的解释和代码,我之后再给修正):

    下面是rotate后的一个有序数组的图。四边形的斜边表示数组中数值的大小。

    在这种情况下数组分了两部分,分别都是有序(递增)的。

    当我们计算了Mid以后,有两种可能,分别用Mid1和Mid2表示。

    1. 如果A[Low] < A[Mid],说明Mid落在区间1中,即图中Mid1的位置。那么,如果target小于A[Mid1],那么继续在Low和Mid1中间搜索;否则,在Mid1和High中间搜索;

    2. 如果A[Low] >= A[Mid],说明Mid落在区间2中,即图中Mid2的位置。同理,如果target小于A[Mid2],那么继续在Low和Mid2中间搜索;否则,在Mid2和High中间搜索。

    这样,平均地,我们每次剔除一半数据,时间复杂度是O(logn)。

    代码如下:

    private static int search2(int[] A, int target){
            int lo = 0;
            int hi = A.length - 1;
            while(lo <= hi){
                int mid = lo + (hi - lo)/2;
                if(target == A[mid]) return mid;
                if(A[mid] > A[lo]){ // 他先判断mid和最左边的值
                    if(target >= A[lo] && target < A[mid]){
                        hi = mid - 1;
                    }else {
                        lo = mid + 1;
                    }
                }else {
                    if(target <= A[hi] && target > A[mid]){
                        lo = mid + 1;
                    }else {
                        hi = mid -1;
                    }
                }
            }
            return -1;
        }

    上述是java的代码。他是先判断A[mid]和最左边的大小,这个时候如果例子是[3,1],要找的target是1,那么就会出现问题。因为先判断左边的时候,此时mid和l下标都是0,且值3大于目标,这时判断A[mid] > A[l]不成立,所以认为要在右边找。但是这是虽然target<=A[hi]成立,但是target>A[mid]不成立,因为此时A[mid]为3大于1.所以执行hi = mid -1;这时就巧妙的错过了正确的答案1.导致输出-1.

    考虑到这样的case情况,如果先考虑A[mid]和最右边的大小,就可以通过。

    class Solution {
    public:
        int search(int A[], int n, int target) 
        {
            int l = 0, r = n - 1;
    
            while(l <= r)
            {
                int mid = (l + r)/2;
                if (A[mid] == target)
                    return mid;
                if (A[mid] < A[r]) //先考虑和右边的比较
                {
                    if (A[mid] < target && A[r] >= target)
                        l = mid + 1;
                    else
                        r = mid - 1;
                }
                else
                {
                    if (A[mid] > target && A[l] <= target)
                        r = mid - 1;
                    else
                        l = mid + 1;
                }
            }
            return -1;
        }
    };

    如果确实要从左边开始的话也行,那就是利用比值的时候和mid+或者-1的值去比而不是直接和mid比,因为mid已经判断过是不是等于target了。这样也可以避免之前出现的错误。代码如下:

    int search(int A[], int n, int target) {
            int lo = 0;
            int hi = n - 1;
            while(lo <= hi){
                int mid = lo + (hi - lo)/2;
                if(target == A[mid]) return mid;
                if(A[mid] > A[lo]){
                    if(target >= A[lo] && target <= A[mid-1]){ // mid-1 的话就是小于等于了
                        hi = mid - 1;
                    }else {
                        lo = mid + 1;
                    }
                }else {
                    if(target <= A[hi] && target >= A[mid+1]){
                        lo = mid + 1;
                    }else {
                        hi = mid -1;
                    }
                }
            }
            return -1;
        }

     2015/03/29: Python

    class Solution:
        # @param A, a list of integers
        # @param target, an integer to be searched
        # @return an integer
        def search(self, A, target):
            left, right = 0, len(A)-1
            while left <= right:
                mid = (left + right) / 2
                if A[mid] == target:
                    return mid
                if A[mid] < A[right]:
                    if A[mid] < target and target <= A[right]:
                        left = mid + 1
                    else:
                        right = mid -1
                else:
                    if A[mid] > target and target >= A[left]:
                        right = mid - 1
                    else:
                        left = mid + 1
            return -1
  • 相关阅读:
    区块链入门
    上海美食餐厅
    《OD学hadoop》20160910某旅游网项目实战
    《OD学hadoop》20160904某旅游网项目实战
    《OD学hadoop》20160903某旅游网项目实战
    qt5-自定义类
    qt5-Qt Creator使用
    qt5-QPushButton按钮
    qt5-工程文件的介绍--快捷键
    电路分析-电阻
  • 原文地址:https://www.cnblogs.com/higerzhang/p/4046693.html
Copyright © 2011-2022 走看看