【二分】搜索旋转数组

文章目录

  • 不重复数组找最小值,返回下标
  • 重复数组找最小值,返回下标
  • 不重复数组找target,返回下标
  • 重复数组找target,返回bool
  • 重复数组找target,返回下标

不重复数组找最小值,返回下标

【二分】搜索旋转数组_第1张图片

【二分】搜索旋转数组_第2张图片

class Solution {
    public int findMin(int[] nums) {
        int n = nums.length;
        int l = 0;
        int r = n - 1;
        while(l <= r){
            if(l == r || nums[l] < nums[r]){
                break;
            }
            int mid = l + (r - l) / 2;
            if(nums[mid] >= nums[l]){
                // [l, mid]有序
                l = mid + 1;
            }else{
                // [mid, r]有序
                r = mid;
            }
        }
        return nums[l];
    }
}
class Solution {
    public int findMin(int[] nums) {
        int n = nums.length;
        int l = 0;
        int r = n - 1;
        while(l <= r){
            if(l == r || nums[l] <= nums[r]){
                // [l,r]已经有序
                break;
            }
            int mid = l + (r - l) / 2;
            if(nums[mid] > nums[l]){
                l = mid + 1;
            }else if(nums[mid] < nums[l]){
                r = mid;
            }else{
                l++;
            }
        }
        return nums[l];
    }
}

重复数组找最小值,返回下标

【二分】搜索旋转数组_第3张图片

【二分】搜索旋转数组_第4张图片

nums[mid] < nums[l],说明最小值肯定在(low, mid]区间内,则r = mid

【二分】搜索旋转数组_第5张图片
nums[mid] > nums[l],说明最小值肯定在mid右侧,(mid,r]区间内,则l = mid + 1

【二分】搜索旋转数组_第6张图片

nums[mid] == nums[l],无法判断最小值在哪个区间,但一定在(l, r]内部
我们假设nums[l]、nums[mid]就是最小值,那我们可以排除l,即l++,因为nums[mid]可以替代nums[l]
若nums[l]、nums[mid]不是最小值,我们直接l++

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

class Solution {
    public int findMin(int[] nums) {
        int n = nums.length;
        int l = 0;
        int r = n - 1;
        while(l <= r){
            if(l == r || nums[l] <= nums[r]){
                // [l,r]已经有序
                break;
            }
            int mid = l + (r - l) / 2;
            if(nums[mid] > nums[l]){
                l = mid + 1;
            }else if(nums[mid] < nums[l]){
                r = mid;
            }else{
                l++;
            }
        }
        return nums[l];
    }
}

不重复数组找target,返回下标

【二分】搜索旋转数组_第7张图片

class Solution {
    public int search(int[] nums, int target) {
        int n = nums.length;
        int l = 0;
        int r = n - 1;
        while(l <= r){
            int mid = l + (r - l) / 2;
            if(target == nums[mid]){
                return mid;
            }
            if(nums[mid] > nums[l]){
                // [l, mid]有序
                if(target >= nums[l] && target < nums[mid]){
                    // 在有序区间内
                    r = mid - 1;
                }else{
                    l = mid + 1; 
                }
            }else if(nums[mid] < nums[l]){
                // [mid, r]有序
                if(target > nums[mid] && target <= nums[r]){
                    // 在有序区间内
                    l = mid + 1;
                }else{
                    r = mid - 1; 
                }
            }else{
                l++;
            }
        }
        return -1;
    }
}

重复数组找target,返回bool

【二分】搜索旋转数组_第8张图片

class Solution {
    public int search(int[] nums, int target) {
        int n = nums.length;
        int l = 0;
        int r = n - 1;
        while(l <= r){
            int mid = l + (r - l) / 2;
            if(target == nums[mid]){
                return mid;
            }
            if(nums[mid] > nums[l]){
                // [l, mid]有序
                if(target >= nums[l] && target < nums[mid]){
                    // 在有序区间内
                    r = mid - 1;
                }else{
                    l = mid + 1; 
                }
            }else if(nums[mid] < nums[l]){
                // [mid, r]有序
                if(target > nums[mid] && target <= nums[r]){
                    // 在有序区间内
                    l = mid + 1;
                }else{
                    r = mid - 1; 
                }
            }else{
                l++;
            }
        }
        return -1;
    }
}

重复数组找target,返回下标

【二分】搜索旋转数组_第9张图片

class Solution {
    public int search(int[] nums, int target) {
        int l = 0;
        int r = nums.length - 1;
        if (r == -1)
            return -1;
        while (l < r) {                                         // 循环结束条件l==r
            int mid = l + (r - l) / 2;
            if (nums[l] < nums[mid]) {                              // 如果左值小于中值,说明左边区间升序               
                if (nums[l] <= target && target <= nums[mid]) {     // 如果目标在左边的升序区间中,右边界移动到mid
                    r = mid;
                } else {                                               // 否则目标在右半边,左边界移动到mid+1
                    l = mid + 1;
                }
            } else if (nums[l] > nums[mid]) {                       // 如果左值大于中值,说明左边不是升序,右半边升序
                if (nums[l] <= target || target <= nums[mid]) {     // 如果目标在左边,右边界移动到mid
                    r = mid;
                } else {                                               // 否则目标在右半边,左边界移动到mid+1
                    l = mid + 1;
                }
            } else if (nums[l] == nums[mid]) {                      // 如果左值等于中值,可能是已经找到了目标,也可能是遇到了重复值
                if (nums[l] != target) {                            // 如果左值不等于目标,说明还没找到,需要逐一清理重复值。
                    l++;
                } else {                                               // 如果左值等于目标,说明已经找到最左边的目标值 
                    r = l;                                      // 将右边界移动到l,循环结束
                }
            }
        }
        return (nums[l] == target) ? l : -1;                     // 返回l,或者-1
    }
}

你可能感兴趣的:(算法,数据结构)