LeetCode——搜索旋转排序数组题目(二分查找)

153.寻找旋转排序数组中的最小值
33. 搜索旋转排序数组
81. 搜索旋转排序数组 II
154. 寻找旋转排序数组中的最小值 II

33. 搜索旋转排序数组

LeetCode——搜索旋转排序数组题目(二分查找)_第1张图片

解题思路:

这些题都是利用二分查找的思想,因为本来有序的数组,在经过旋转后,分成了两部分各自有序的排列,在旋转后的数组中寻找一个target,可以证明的是target一定会落在一个有序的区间内,那么只需要去确定这个区间就可以了。
nums[mid] > nums[left]) { //前半部分有序中间的这个值大于left,根据数组是有序旋转得到的,说明落到了前半部分有序的地方,例如3,4,5,6,7,1,2
相反,说明是后半部分有序,例如,6,7,1,2,3,4,5
二分题目很多细节需要注意。

参考代码:

153.寻找旋转排序数组中的最小值

    public int findMin(int[] nums) {
        int left=0;
        int right=nums.length-1;
        while (left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]>nums[right]){
                left=mid+1;
            }else {
                right=mid;
            }
        }
        return nums[left];
    }

33. 搜索旋转排序数组

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

        }
        return -1;
    }

81. 搜索旋转排序数组 II

       public boolean search(int[] nums, int target) {
        if (nums.length < 1) {
            return false;
        }
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return true;
            }
            if (nums[mid] == nums[left]) {
                left++;
                continue;
            } else if (nums[mid] > nums[left]) {    //前半部分有序
                if (target >= nums[left] && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }

            } else {                         //后半部分有序
                if (target > nums[mid] && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return false;
    }

154. 寻找旋转排序数组中的最小值 II

这道题有一些细节的问题:
1、为什么right=mid,left=mid+1?
因为普通的二分,我们一般会写成right=mid-1,left=mid+1,在选择到底是mid的那种情况的时候,只要是看结果可能在mid中出现来决定的,例如nums[mid]nums[right],这个时候,mid的位置都比right大了,所以结果肯定不会是mid,所以我们可以直接更新left指针为mid+1.
2、right=right-1会影响结果吗?答案是不会,因为如果说right指针左移的过程中,将最小的元素排除掉了,那么这个条件就是mid==right, 有两个最小的了,自相矛盾了,所以说不会出现这种情况。

    public int findMin(int[] nums) {
        int left=0;
        int right=nums.length-1;
        while (left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]<nums[right]){
                right=mid;
            }else if(nums[mid]>nums[right]){
                left=mid+1;
            }else {
                right=right-1;
            }
        }
        return nums[left];
    }

你可能感兴趣的:(LeetCode,数据结构,算法,二分法,leetcode,排序算法)