LeetCode 每日一题笔记 日期:2025.12.01 题目:2141.同时运行 N 台电脑的最长时间

LeetCode 每日一题笔记

0. 前言

  • 日期:2025.12.01
  • 题目:2141.同时运行 N 台电脑的最长时间
  • 难度:困难
  • 标签:数组 二分查找 贪心

1. 题目理解

问题描述

n 台电脑,给定整数数组 batteries(第 i 个电池可让一台电脑运行 batteries[i] 分钟)。初始时每台电脑最多连一个电池,之后可随时断开/连接电池(无时间消耗)。要求让全部 n 台电脑同时运行,返回最长运行分钟数。

示例

示例 1:

输入:n = 2, batteries = 3,3,3

输出:4

解释:总电池容量 9,2台电脑同时运行的理论最大时间为 9/2=4.5,实际可运行 4 分钟(每个电池贡献 3 分钟,总和 9 ≥ 2×4=8)。
示例 2:

输入:n = 3, batteries = 10,10,3,5

输出:8

解释:总容量 28,理论最大 28/3≈9.33,实际验证 8 分钟可行(各电池贡献 8、8、3、5,总和 24 ≥ 3×8=24)。

2. 解题思路

核心观察

  • 若要让 n 台电脑同时运行 T 分钟,总能耗为 n×T,需满足所有电池的有效贡献总和 ≥ n×T
  • 每个电池的有效贡献为 min(电池容量, T)(电池最多为某台电脑提供 T 分钟电量)。

算法步骤

  1. 二分范围确定

    • 左边界 left = 0(最小运行时间);
    • 右边界 right = 总电池容量 / n(理论最大运行时间,总能耗不能超过总电池容量)。
  2. 二分查找

    • 取中间值 mid 作为候选运行时间;
    • 验证 mid 是否可行(计算所有电池的有效贡献总和,判断是否 ≥ n×mid);
    • 若可行,记录 mid 并尝试更大时间(右移左边界);
    • 若不可行,尝试更小时间(左移右边界)。

3. 代码实现

java 复制代码
class Solution {
    public long maxRunTime(int n, int[] batteries) {
        // 计算所有电池总容量(用long避免溢出)
        long sum = 0;
        for (int b : batteries) sum += b;
        
        // 二分查找的范围
        long left = 0, right = sum / n;
        long ans = 0;
        
        while (left <= right) {
            long mid = (left + right) / 2;
            // 验证mid分钟是否可行
            if (check(mid, n, batteries)) {
                ans = mid; // 记录可行的最大时间
                left = mid + 1; // 尝试更大时间
            } else {
                right = mid - 1; // 尝试更小时间
            }
        }
        return ans;
    }
    
    // 验证函数:判断是否能让n台电脑同时运行T分钟
    private boolean check(long T, int n, int[] batteries) {
        long total = 0;
        for (int b : batteries) {
            total += Math.min(b, T); // 每个电池最多贡献T分钟
            if (total >= n * T) return true; // 提前终止,节省时间
        }
        return total >= n * T;
    }
}

4. 代码优化说明

优化版将验证逻辑内联到二分循环中,减少函数调用开销(仅逻辑合并,核心思路不变):

java 复制代码
class Solution {
    public long maxRunTime(int n, int[] batteries) {
        long sum = 0;
        for (int cap : batteries) {
            sum += cap;
        }
        
        long left = 0, right = sum / n, ans = 0;
        while (left <= right) {
            long mid = left + (right - left) / 2; // 避免left+right溢出
            long total = 0;
            for (int cap : batteries) {
                total += Math.min(cap, mid);
            }
            if (total >= n * mid) {
                ans = mid;
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return ans;
    }
}

5. 复杂度分析

  • 时间复杂度:(O(m \times \log(\text{sum}/n)))

    • m 是电池数量,每次验证需遍历所有电池((O(m)));
    • 二分查找的次数为 (\log(\text{sum}/n))(sum为总电池容量)。
  • 空间复杂度:(O(1))

    • 仅使用常量级额外空间。

6. 总结

  • 核心思路是二分查找 + 贪心验证:通过二分缩小运行时间的候选范围,用贪心计算电池有效贡献来验证可行性;
  • 关键技巧是利用"每个电池最多贡献 T 分钟"的贪心策略,快速判断候选时间是否可行;
  • 该方法高效解决了"最大化同时运行时间"的问题,避免了暴力枚举的高时间复杂度。
相关推荐
雾沉川2 小时前
Windows11 Enterprise/IoT LTSC2024 系统介绍与完整安装技术教程
电脑
漫友也是程序猿3 小时前
ddraw.dll异常排查:旧游戏图形接口、兼容性模式和DirectX组件检查
程序人生·游戏·电脑
8Qi84 小时前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
和平宇宙4 小时前
AI笔记005. hermes-DeepSeek V4 Pro, 128K上下文引发的探索
前端·人工智能·笔记
十月的皮皮4 小时前
C语言学习笔记20260606- 求月份天数三种写法
c语言·笔记·学习
cmes_love4 小时前
Level 2逐笔成交历史数据下载方法笔记
数据库·笔记·oracle
Cloud_Shy6185 小时前
解读《Effective Python 3rd Edition》:从练气到老魔(第五章 Item 30 - 32)
开发语言·人工智能·笔记·python·学习方法
问心无愧05136 小时前
ctf show web入门110
前端·笔记
道一236 小时前
Windows系统查看端口占用进程的3种实用方法
windows·笔记
lunzi_08267 小时前
【学习笔记】《Python编程 从入门到实践》第8章:函数定义、参数传递与模块导入
笔记·python·学习