Leetcode2528. 最大化城市的最小电量

Every day a Leetcode

题目来源:2528. 最大化城市的最小电量

解法1:二分查找 + 前缀和 + 差分数组

看到「最大化最小值」或者「最小化最大值」就要想到二分答案,这是一个固定的套路。

为什么?一般来说,二分的值越大,越能/不能满足要求;二分的值越小,越不能/能满足要求,有单调性,可以二分。

二分答案 minPower,从左到右遍历 stations,如果 stations[i] 电量不足 minPower,那么需要建供电站来补足。

在哪建供电站最好呢?

由于 i 左侧的不需要补足,所以贪心地在 min⁡(i+r,n−1) 处建是最合适的,恰好让 i 在覆盖范围的边界上。

设需要建 m 个供电站,那么需要把 [i,min⁡(i+2r,n−1)] 范围内的电量都增加 m。

方法很多,用差分数组来更新是最简单的。

最后判断修建的供电站是否超过 k,如果超过说明 minPower 偏大,否则说明偏小。

代码:

/*
 * @lc app=leetcode.cn id=2528 lang=cpp
 *
 * [2528] 最大化城市的最小电量
 */

// @lc code=start
class Solution
{
   
public:
    long long maxPower(vector<int> &stations, int r, int k)
    {
   
        int n = stations.size();
        vector<long long> preSum(n + 1, 0);
        long long diff[n];
        vector<long long> power(n, 0);

        // 求前缀和
        for (int i = 1; i <= n; i++)
            preSum[i] = preSum[i - 1] + stations[i - 1];
        // 求电量
        for (int i = 0; i < n; ++i)
            power[i] = preSum[min(i + r + 1, n)] - preSum[max(i - r, 0)];

        auto check = [&](long long min_power) -> bool
        {
   
            memset(diff, 0, sizeof(diff)); // 重置差分数组
            long long sum_d = 0, need = 0;
            for (int i = 0; i < n; i++)
            {
   
                sum_d += diff[i]; // 累加差分值
                long long m = min_power - power[i] - sum_d;
                if (m > 0)
                {
    // 需要 m 个供电站
                    need += m;
                    if (need > k)
                        return false; // 提前退出这样快一些
                    sum_d += m;       // 差分更新
                    if (i + r * 2 + 1 < n)
                        diff[i + r * 2 + 1] -= m; // 差分更新
                }
            }
            return true;
        };

        // 二分查找,开区间写法
        long long left = *min_element(power.begin(), power.end());
        long long right = left + k + 1;
        while (left + 1 < right)
        {
   
            long long mid = left + (right - left) / 2;
            if (check(mid))
                left = mid;
            else
                right = mid;
        }
        return left;
    }
};
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(nlogk),其中 n 为数组 stations 的长度。二分需要循环 O(log⁡k) 次。

空间复杂度:O(n),其中 n 为数组 stations 的长度。

相关推荐

  1. leetcode2529-正整数和负整数大计数

    2024-02-02 09:30:02       30 阅读
  2. leetcode2529--正整数和负整数大计数

    2024-02-02 09:30:02       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-02 09:30:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-02 09:30:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-02 09:30:02       82 阅读
  4. Python语言-面向对象

    2024-02-02 09:30:02       91 阅读

热门阅读

  1. 81.如何评估一台服务器能开启多少Go协程

    2024-02-02 09:30:02       46 阅读
  2. 【笔记】Helm-5 Chart模板指南-6 流控制

    2024-02-02 09:30:02       51 阅读
  3. OR-Tools的CP-SAT求解器常用参数设置与说明

    2024-02-02 09:30:02       51 阅读
  4. 2024美赛数学建模F题思路&源码

    2024-02-02 09:30:02       59 阅读
  5. 关于在MacOS安装虚拟机的全过程

    2024-02-02 09:30:02       49 阅读
  6. TP5手动集成GatewayWorker

    2024-02-02 09:30:02       54 阅读