[LeetCode] Search in Rotated Sorted Array

https://leetcode.com/problems/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.

solution 1

如果是一个未经旋转的有序数组,显然可以直接用二分查找来做。经过旋转的数组,其实本质就是两个排序数组,我们可以分别在两个数组中进行二分查找,难点是找到两个数组的分界线,用遍历的方式来寻找分界线复杂度为o(n),显然不是我们期待的solution,其实只要意识到整个数组最左边与最右边两个值的特殊性,我们同样可以使用二分的方式来寻找分界线。代码如下:

class Solution {

public:

    int search(vector<int>& nums, int target) {

        if (nums.empty()) {

            return -1;

        }

        

        /* without rotating, excute binary search directly */

        int left = 0, right = nums.size() - 1;

        if (nums[left] <= nums[right]) {

            return binarySearch(nums, left, right, target);

        }

        

        /* include two elements at least */

        left = determineBoundary(nums);

        right = left + 1;

        if (nums[0] <= target && target <= nums[left]) {

            return binarySearch(nums, 0, left, target);

        } else if (nums[right] <= target && target <= nums[nums.size() - 1]) {

            return binarySearch(nums, right, nums.size() - 1, target);

        } else {

            return -1;

        }

    }

    

private:

    int binarySearch(const vector<int> &nums, const int start, const int end, int target) {

        int left = start, right = end, middle;

        

        while (left + 1 < right) {

            middle = (left + right) >> 1;

            if (target == nums[middle]) {

                return middle;

            } else if (target > nums[middle]) {

                left = middle;

            } else if (target < nums[middle]) {

                right = middle;

            }

        }

        

        if (target == nums[left]) {

            return left;

        }

        

        if (target == nums[right]) {

            return right;

        }

        

        return -1;

    }

    

    int determineBoundary(const vector<int> &nums) {

        int leftValue = nums[0], rightValue = nums[nums.size() - 1];

        int left = 0, right = nums.size() - 1, middle;

        

        while (left + 1 < right) {

            middle = (left + right) >> 1;

            

            if (leftValue < nums[middle]) {

                left = middle;

            }

            

            if (nums[middle] < rightValue) {

                right = middle;

            }

        }

        

        return left;

    }

};

solution 2

以上的方案我们通过寻找两个排序数组的分界线,从而对其分别使用二分查找来完成搜索。实际上,该题不必如此繁琐,我们可以省去寻找分界线的步骤,直接进行二分查找。代码如下:

// author: Jian-xin Zhou



class Solution {

public:

    int search(vector<int>& nums, int target) {

        if (nums.empty()) {

            return -1;

        }

        

        int left = 0, right = nums.size() - 1, middle;

        

        while (left + 1 < right) {

            middle = (left + right) >> 1;

            

            if (target == nums[middle]) {

                return middle;

            }

            

            if (nums[left] < nums[middle]) {

                if (nums[left] <= target && target < nums[middle]) {

                    right = middle;

                } else {

                    left = middle;

                }

            }

            

            if (nums[middle] < nums[right]) {

                if (nums[middle] < target && target <= nums[right]) {

                    left = middle;

                } else {

                    right = middle;

                }

            }

        }

        

        if (target == nums[left]) {

            return left;

        }

        

        if (target == nums[right]) {

            return right;

        }

        

        return -1;

    }

};

你可能感兴趣的:(LeetCode)