二分查找:寻找最小值与点名

这两道题都使用二分查找。真正需要判断的不是"套哪一个模板",而是:mid 对应的位置是否仍可能成为答案。如果可能,就必须保留;如果不可能,才可以越过它。

文章目录

一、二分查找的边界判断

二分查找每次都要排除一段不可能包含答案的区间。更新边界前,可以先问两个问题:

  1. 答案可能等于 mid 吗?
  2. 循环结束时,答案由区间中的元素表示,还是由边界位置表示?

这两个问题决定了应该使用 right = mid、right = mid - 1,还是 left = mid + 1。

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

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

旋转后的数组可以看成两段递增区间。与其判断 mid 属于图中的哪一段,不如直接比较 nums[mid] 与右边界 nums[right]。

  • 当 nums[mid] < nums[right] 时,mid 到 right 是递增的,最小值位于 [left, mid]。mid 本身仍可能是最小值,因此令 right = mid。
  • 当 nums[mid] > nums[right] 时,mid 位于旋转点左侧,最小值只能位于 [mid + 1, right]。此时 mid 不可能是答案,因此令 left = mid + 1。

题目保证元素互不相同,而且循环中 mid < right,所以不需要处理 nums[mid] == nums[right]。

java 复制代码
class Solution {
    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 {
                left = mid + 1;
            }
        }
        return nums[left];
    }
}

循环始终保证最小值位于闭区间 [left, right]。当 left == right 时,区间中只剩一个元素,它就是最小值。

时间复杂度为 O(log n),空间复杂度为 O(1)。

三、点名

LCR 173. 点名

如果没有同学缺席,学号与数组下标相同。缺失位置出现后,后面的学号都会比下标大 1:

  • 缺失位置之前:records[i] == i;
  • 缺失位置及其之后:records[i] == i + 1。

因此,这道题可以转化为寻找第一个发生偏移的位置。

设缺失学号为 p。这份代码维护的不变量是 p 始终位于 [left, right + 1],其中 right + 1 也可能是答案。

java 复制代码
class Solution {
    public int takeAttendance(int[] records) {
        int left = 0;
        int right = records.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (records[mid] == mid + 1) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
}

当 records[mid] == mid + 1 时,有 p <= mid,因此令 right = mid - 1。虽然新的待检查下标区间不再包含 mid,但新的 right + 1 正好等于 mid,所以 p == mid 的情况并没有丢失。否则有 records[mid] == mid,说明 p > mid,令 left = mid + 1。

循环结束时 left == right + 1,不变量收缩为唯一位置 p == left。若缺少的是最后一个学号,数组中不会出现偏移,此时 left 会自然移动到 records.length,仍然得到正确答案。

时间复杂度为 O(log n),空间复杂度为 O(1)。

相关推荐
yi0114 小时前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
灯澜忆梦7 小时前
【面向对象编程C++】| 基础语法
java·c++·算法
禾小西7 小时前
Redis 数据结构:快速的 Redis 有哪些慢操作?
数据结构·数据库·redis
小蒋观天下7 小时前
专项方案:大场景港口AI安防、多干扰环境下的算法调优与落地实操
人工智能·深度学习·算法·安全·机器学习·计算机视觉·ai大模型
Evand J7 小时前
【电机滤波例程5】渐消因子自适应扩展卡尔曼滤波(EKF),MATLAB。PMSM负载突变下的状态估计。附下载链接
算法·matlab
H.莓飛7 小时前
【数据结构】二叉树_OJ题
linux·开发语言·数据结构·算法
好想像大佬一样能够ak所有8 小时前
Leetcode35.搜索插入位置
数据结构·算法·leetcode
aqiu1111118 小时前
【C++算法打怪专栏】LeetCode 165. 比较版本号(双指针与字符串流法)
c++·算法·leetcode
黄金龙PLUS8 小时前
如何基于置换算法来设计对称加密算法
算法·网络安全·密码学·哈希算法·同态加密
不会就选b8 小时前
算法日常・每日刷题--<动态规划>14
算法