剑指offer - 面试题11 旋转数组的最小数字

题目链接:旋转数组的最小数字

第一种:正确写法(num[m]和nums[r]比较)

cpp 复制代码
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @return int整型
     */
    int minNumberInRotateArray(vector<int>& nums) {
        // write code here
        int l = 0, m = 0, r = nums.size() - 1;
        while (l < r) { // 将结果框在[l,r]的范围内,因此当l==r时,代表就是结果
            m = (l + r) / 2; // 此处在l=r-1时要注意死循环,因为循环条件时l < r,如果在l根据m改变时,必须给l赋值m+1,因为直接赋值为m就会导致死循环。(此处只需要注意l=m+1,而r=m是可以的,这是因为(l+r)/2的结果可能等于l,但不可能等于r)
            if (nums[m] > nums[r]) {
                l = m + 1; // 说明m是在第一个上升数组中,且m不可能是最小值,所以m这个位置不需要保留,同时为了避免死循环,l=m+1而不是l=m
            } else if (nums[m] < nums[r]) {
                r = m; // 说明m是在第二个上升数组中,且m有可能是结果的位置,因此m必须要保留,r=m而不是r=m-1
            } else {
                r--; // 此处就是第一次没想到的解法,当nums[m] == nums[r]时,没法确定是第一个还是第二个上升数组,但能确定的是,r这个位置可以不要了,因为有m在保留着结果(m不可能等于r,因为如果m==r的话,说明l==r,那么循环就走不到这里了。为了缩小结果集范围,直接r--就可以了)
            }
        }
        return nums[l];
    }
};

但是很神奇的是,上面的代码都是和num[r]比较的,但如果像下面这么写,有些用例就是失败的

第二种错误写法:nums[m]和num[l]比较

cpp 复制代码
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @return int整型
     */
    int minNumberInRotateArray(vector<int>& nums) {
        // write code here
        int l = 0, m = 0, r = nums.size() - 1;
        while (l < r) {
            m = (l + r) / 2;
            if (nums[m] > nums[l]) {
                l = m + 1;
            } else if (nums[m] < nums[l]) {
                r = m;
            } else {
                l++;
            }
        }
        return nums[l];
    }
};

上面的代码表明看起来是对的,但这段代码只能通过部分用例。

因为存在特殊情况,即在旋转0个数字情况下,nums[m]是一定会大于num[l],此时按照上面的代码,l=m+1,l会越加越多,离正确答案nums[0]越来越远了。

因此这就是为什么要按照第一种写法,nums[m]和num[r]进行比较。在旋转0个数字这种特殊情况,nums[m]<num[r]是永远成立的,此时的操作正好是r = m,就不会错过正确答案。

例如[1,0,1,1,1]这个输入,nums[m]和nums[l]比较这个上面的第二种代码就是错误的。

第一轮l=0,r=4,m=2。此时nums[l]==nums[r],因此l++

第二轮l=1,r=4,m=2。此时[l,r]就是[0,1,1,1]这个升序的序列了,就是上面所说的特殊场景,nums[m] > nums[l],按照第二种代码的逻辑,l = m+1,l=3。这样直接就把正确答案跳过去了。

相关推荐
SELSL18 分钟前
SQLite3的API调用实战例子
linux·数据库·c++·sqlite3·sqlite实战
什么半岛铁盒40 分钟前
C++项目:仿muduo库高并发服务器-------Channel模块实现
linux·服务器·数据库·c++·mysql·ubuntu
手握风云-42 分钟前
优选算法的寻踪契合:字符串专题
算法
闭着眼睛学算法1 小时前
【华为OD机考正在更新】2025年双机位A卷真题【完全原创题解 | 详细考点分类 | 不断更新题目 | 六种主流语言Py+Java+Cpp+C+Js+Go】
java·c语言·javascript·c++·python·算法·华为od
IT古董1 小时前
【第五章:计算机视觉-项目实战之目标检测实战】2.目标检测实战:中国交通标志检测-(2)中国交通标志检测数据格式转化与读取
算法·目标检测·计算机视觉
MobotStone1 小时前
LLM 采样入门到进阶:理解与实践 Top-K、Top-P、温度控制
算法
ShineSpark1 小时前
C++面试11——指针与引用
c++·面试
杨小码不BUG2 小时前
CSP-J/S初赛知识点精讲-图论
c++·算法·图论··编码·csp-j/s初赛
初圣魔门首席弟子2 小时前
flag使用错误出现bug
c++·bug
Mr_WangAndy2 小时前
C++设计模式_创建型模式_原型模式Prototype
c++·设计模式·原型模式