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 分钟"的贪心策略,快速判断候选时间是否可行;
  • 该方法高效解决了"最大化同时运行时间"的问题,避免了暴力枚举的高时间复杂度。
相关推荐
wdfk_prog20 分钟前
[Linux]学习笔记系列 -- [fs]file_table
linux·笔记·学习
Swift社区40 分钟前
LeetCode 454 - 四数相加 II
java·算法·leetcode
惜.己1 小时前
前端笔记(四)
前端·笔记
多米Domi0111 小时前
0x3f第12天 0-1背包
python·算法·leetcode·动态规划
我命由我123451 小时前
开发中的英语积累 P21:Parentable、Guideline、Manifest、Expire、Condition、Optimize
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
BOF_dcb1 小时前
TCP/IP网络协议
笔记
Lv11770081 小时前
Visual Studio中的常量和只读变量
ide·笔记·c#·visual studio
深蓝海拓1 小时前
PySide6从0开始学习的笔记(十四)创建一个简单的实用UI项目
开发语言·笔记·python·qt·学习·ui·pyqt
其美杰布-富贵-李2 小时前
数据清理与特征工程完整指南
笔记·深度学习·特征工程·训练·数据清理
老王熬夜敲代码2 小时前
计算机网络--IP概念
linux·网络·笔记