每日算法-250409

这是我今天的算法学习记录。


2187. 完成旅途的最少时间

题目描述

LeetCode 2187 题目截图

思路

二分查找

解题过程

为什么可以使用二分查找?

问题的关键在于寻找一个最小 的时间 t,使得在时间 t 内所有公交车完成的总旅途次数 sum 大于等于 totalTrips

我们可以观察到时间的单调性:如果时间 t 内可以完成 totalTrips 次旅途,那么任何大于 t 的时间 t' 肯定也可以完成(甚至完成更多)。反之,如果时间 t 内无法完成 totalTrips 次旅途(即 sum < totalTrips),那么任何小于 t 的时间 t'' 也肯定无法完成。

这种单调性(或称为"二段性")是使用二分查找的前提。我们可以在一个可能的时间范围内(例如从 1 到一个足够大的上限)进行二分查找。

查找目标是什么?

我们要找的是满足 sum >= totalTrips最小 时间 t

二分步骤:

  1. 确定查找范围 [left, right]left 可以是 1,right 可以是一个合理的上界,例如 min(time) * totalTrips(即假设只有最快的车在跑,完成所有旅程所需的时间)。
  2. 取中间时间 mid = left + (right - left) / 2
  3. 计算在 mid 时间内,所有公交车能完成的总旅途次数 sumsum = Σ (mid / time[i]) 对所有 i 求和。
  4. 比较 sumtotalTrips
    • 如果 sum < totalTrips,说明 mid 时间太短,无法完成任务。真正的最短时间一定在 mid 右侧,所以更新 left = mid + 1
    • 如果 sum >= totalTrips,说明 mid 时间可能 是答案,或者可能还有更短的时间也满足条件。我们需要尝试更小的时间,所以更新 right = mid - 1
  5. 循环直到 left > right。最终的 left 就是满足条件的最小时间。

复杂度

  • 时间复杂度 : O ( N log ⁡ M ) O(N \log M) O(NlogM)
    • 其中 N 是公交车的数量 (time.length)。
    • M 是二分查找的时间范围的上界。在代码中,上界设置为 min(time) * totalTrips。每次二分查找需要 O ( N ) O(N) O(N) 的时间来计算 sum 函数,二分查找本身需要 O ( log ⁡ M ) O(\log M) O(logM) 次迭代。
  • 空间复杂度 : O ( 1 ) O(1) O(1)
    • 我们只需要常数级别的额外空间。

Code

java 复制代码
class Solution {
    public long minimumTime(int[] time, int totalTrips) {
        long left = 1, right = Integer.MAX_VALUE;
        for (int x : time) {
            right = Math.min(right, x);
        }
        right *= totalTrips;
        while (left <= right) {
            long mid = left + (right - left) / 2;
            if (sum(time, mid) < totalTrips) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }

    private long sum(int[] arr, long k) {
        long sum = 0;
        for (int x : arr) {
            sum += (k / x);
        }
        return sum;
    }
}

34. 在排序数组中查找元素的第一个和最后一个位置(复习)

题目描述

LeetCode 34 题目截图

今天是第二次写这道题,和上次相比已经理解了步骤,可以完全解决问题了。

详细题解见我之前的博文:每日算法-250405

Code

java 复制代码
class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left = check(nums, target);
        if (left == nums.length || nums[left] != target) {
            return new int[] {-1, -1};
        }
        int right = check(nums, target + 1) - 1;
        return new int[] {left, right};
    }

    private int check(int[] arr, int k) {
        int left = 0, right = arr.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] < k) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
}

2529. 正整数和负整数的最大计数(复习)

题目描述

LeetCode 2529 题目截图

今天是第二次写这道题,写的已经很顺手了,就不过多解释了。

详细题解见我之前的博文:每日算法-250406

Code

java 复制代码
class Solution {
    public int maximumCount(int[] nums) {
        int neg = check(nums, 0);
        int pos = check(nums, 1);
        return Math.max(neg, (nums.length - pos));
    }

    private int check(int[] arr, int k) {
        int left = 0, right = arr.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] < k) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
}

相关推荐
黑屋里的马2 小时前
java的设计模式之桥接模式(Bridge)
java·算法·桥接模式
sin_hielo2 小时前
leetcode 1611
算法·leetcode
李小白杂货铺2 小时前
识别和破除信息茧房
算法·信息茧房·识别信息茧房·破除信息茧房·算法推荐型茧房·观点过滤型茧房·茧房
来荔枝一大筐3 小时前
C++ LeetCode 力扣刷题 541. 反转字符串 II
c++·算法·leetcode
暴风鱼划水3 小时前
算法题(Python)数组篇 | 6.区间和
python·算法·数组·区间和
zl_vslam4 小时前
SLAM中的非线性优-3D图优化之轴角在Opencv-PNP中的应用(一)
前端·人工智能·算法·计算机视觉·slam se2 非线性优化
是苏浙4 小时前
零基础入门C语言之C语言实现数据结构之顺序表应用
c语言·数据结构·算法
lkbhua莱克瓦244 小时前
Java基础——常用算法3
java·数据结构·笔记·算法·github·排序算法·学习方法
小白程序员成长日记4 小时前
2025.11.07 力扣每日一题
数据结构·算法·leetcode
·白小白4 小时前
力扣(LeetCode) ——209. 长度最小的子数组(C++)
c++·算法·leetcode