LeetCode 33,81. Search in Rotated Sorted Array i, ii

1. 题目描述

33

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.

81

Follow up for “Search in Rotated Sorted Array”:
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Write a function to determine if a given target is in the array.

2. 解题思路

这是一个有序数组, 所以我们可以尝试使用二分的思路去解决这个问题, 不过需要注意一个问题,使用二分法的时候, 边界问题的判断。 这里由于不太记得住二分法究竟怎么写了, 于是在自己的代码中加了一个补丁, 特别判断一下 start == stop - 1 的情形

而对于 81 题, 由于允许重复, 我们只需要对有重复部分区域采用遍历即可。

3. code

3.1 code 33

class Solution {
public:
    int search(vector<int>& nums, int target) {
        return helper(nums, 0, nums.size() - 1, target);
    }
private:
    // x --> [start, stop];
    int helper(vector<int>& nums, int start, int stop, int target){
        int res = -1;
        while (start <= stop){
            int mid = start + ((stop - start) >> 1);
            if (nums[mid] == target)
                return mid;

            if (start == stop)
                break;

            // 我是补丁
            if (start == stop - 1){
                if (nums[stop] == target)
                    return stop;
                break;
            }

            if (nums[start] < nums[mid]){
                if (nums[start] <= target && nums[mid] > target)
                    stop = mid - 1;
                else
                    start = mid + 1;
            }
            else{
                if (nums[mid] < target && nums[stop] >= target)
                    start = mid + 1;
                else
                    stop = mid - 1;
            }
        }

        return res;
    }
};

3.2 81 code

class Solution {
public:
    bool search(vector<int>& nums, int target) {
        return helper(nums, 0, nums.size() - 1, target) >= 0;
    }

private:
    // x --> [start, stop];
    int helper(vector<int>& nums, int start, int stop, int target){
        int res = -1;
        while (start <= stop){
            int mid = start + ((stop - start) >> 1);
            if (nums[mid] == target)
                return mid;

            if (start == stop)
                break;

            // 我是补丁
            if (start == stop - 1){
                if (nums[stop] == target)
                    return stop;
                break;
            }

            // 遍历搜索
            if (nums[start] == nums[mid] || nums[stop] == nums[mid] || nums[start] == nums[stop]){
                for (int i = start; i != stop + 1; i++){
                    if (nums[i] == target)
                        return i;
                }

                return -1;
            }

            if (nums[start] < nums[mid]){
                if (nums[start] <= target && nums[mid] > target)
                    stop = mid - 1;
                else
                    start = mid + 1;
            }
            else{
                if (nums[mid] < target && nums[stop] >= target)
                    start = mid + 1;
                else
                    stop = mid - 1;
            }
        }

        return res;
    }
};

4. 大神解法

4.1 33 demo1 先修复旋转数组, 再查找

这段代码, 主要是通过先利用二分查找, 找到最小值的位置, 然后根据这个最小值的位置, 可以推算出该旋转数组和该数组之间的转化关系, 利用二分查找即可, what a brilliant solution!!!

class Solution {
public:
    int search(int A[], int n, int target) {
        int lo=0,hi=n-1;
        // find the index of the smallest value using binary search.
        // Loop will terminate since mid < hi, and lo or hi will shrink by at least 1.
        // Proof by contradiction that mid < hi: if mid==hi, then lo==hi and loop would have been terminated.
        while(lo<hi){
            int mid=(lo+hi)/2;
            if(A[mid]>A[hi]) lo=mid+1;
            else hi=mid;
        }
        // lo==hi is the index of the smallest value and also the number of places rotated.
        int rot=lo;
        lo=0;hi=n-1;
        // The usual binary search and accounting for rotation.
        while(lo<=hi){
            int mid=(lo+hi)/2;
            int realmid=(mid+rot)%n;
            if(A[realmid]==target)return realmid;
            if(A[realmid]<target)lo=mid+1;
            else hi=mid-1;
        }
        return -1;
    }
};

4.2 33 demo2 思路和我们的一致

public class Solution {
public int search(int[] A, int target) {
    int lo = 0;
    int hi = A.length - 1;
    while (lo < hi) {
        int mid = (lo + hi) / 2;
        if (A[mid] == target) return mid;

        if (A[lo] <= A[mid]) {
            if (target >= A[lo] && target < A[mid]) {
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
        } else {
            if (target > A[mid] && target <= A[hi]) {
                lo = mid + 1;
            } else {
                hi = mid - 1;
            }
        }
    }
    return A[lo] == target ? lo : -1;
}
}

4.3 81 demo

由于当发生重复的时候, A[m] == A[l], 可以将 l++, 因为这个l 的值会在后面的内容中再次出现的。。。

bool search(int A[], int n, int key) {
    int l = 0, r = n - 1;
    while (l <= r) {
        int m = l + (r - l)/2;
        if (A[m] == key) return true; //return m in Search in Rotated Array I
        if (A[l] < A[m]) { //left half is sorted
            if (A[l] <= key && key < A[m])
                r = m - 1;
            else
                l = m + 1;
        } else if (A[l] > A[m]) { //right half is sorted
            if (A[m] < key && key <= A[r])
                l = m + 1;
            else
                r = m - 1;
        } else l++;
    }
    return false;
}

你可能感兴趣的:(LeetCode)