每日算法-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;
    }
}

相关推荐
.格子衫.6 分钟前
018数据结构之队列——算法备赛
数据结构·算法
怎么没有名字注册了啊1 小时前
求一个矩阵中的鞍点
数据结构·算法
Greedy Alg1 小时前
LeetCode 74. 搜索二维矩阵
算法
小猪咪piggy2 小时前
【算法】day7 滑动窗口+二分查找
算法
仟千意2 小时前
数据结构:二叉树
数据结构·算法
一水鉴天2 小时前
整体设计 逻辑系统程序 之34七层网络的中台架构设计及链路对应讨论(含 CFR 规则与理 / 事代理界定)
人工智能·算法·公共逻辑
DuHz2 小时前
C程序中的数组与指针共生关系
linux·c语言·开发语言·嵌入式硬件·算法
而后笑面对2 小时前
力扣2025.10.19每日一题
算法·leetcode·职场和发展
·白小白3 小时前
力扣(LeetCode) ——11.盛水最多的容器(C++)
c++·算法·leetcode
沐浴露z4 小时前
【JVM】详解 垃圾回收
java·jvm·算法