剑指Offer11 -- 二分

1. 题目描述

元素可重复的旋转数组的最小值



2. 思路

ref
对二分的奇怪知识增加了!
需要注意的一点是,由于我们在二分过程中改变了 \(r\) 的位置,因此不能一直使用预先存放的 \(nums[r]\)



3. 代码

/*
    本题与 153 题的区别在于,有重复元素
    如果有重复元素,我们就无法确定左右区间
    也就无法二分了 😭
    但是事实真的是这样吗?
    事实上,如果我们遇到了边界情况,即:
    nums[mid] == last(nums[n-1])
    我们可以直接“删掉末尾元素”,这不会对答案求解有影响,因为此时有两种情况
    1. last是最小值,那么 nums[mid] 也是最小值,删去也无妨
    2. last不是最小值,此时删去当然无影响
    如果last是最小值,那么 nums[mid] 也是最小值
*/
class Solution {
public:
    int minArray(vector<int>& nums) {
        int l = 0, r = nums.size() - 1;
        // int last = nums[r]; // 错误!!!!我们的last是动态变化的
        while(l < r) {
            int mid = l + r >> 1;
            if(nums[mid] == nums[r])   r -- ;  // 删掉,神来一笔!
            else if(nums[mid] > nums[r])   l = mid + 1; // left
            else    r = mid;    // right
        }
        return nums[l];
    }
};
posted @ 2023-03-18 19:56  光風霽月  阅读(9)  评论(0编辑  收藏  举报