首页 > 其他分享 >LeetCode 2528. 最大化城市的最小电量

LeetCode 2528. 最大化城市的最小电量

时间:2024-07-04 12:57:13浏览次数:3  
标签:stations int 城市 min 2528 电量 供电站 LeetCode

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

给你一个下标从 0 开始长度为 n 的整数数组 stations ,其中 stations[i] 表示第 i 座城市的供电站数目。

每个供电站可以在一定 范围 内给所有城市提供电力。换句话说,如果给定的范围是 r ,在城市 i 处的供电站可以给所有满足 |i - j| <= r 且 0 <= i, j <= n - 1 的城市 j 供电。

  • |x| 表示 x 的 绝对值 。比方说,|7 - 5| = 2 ,|3 - 10| = 7 。

一座城市的 电量 是所有能给它供电的供电站数目。

政府批准了可以额外建造 k 座供电站,你需要决定这些供电站分别应该建在哪里,这些供电站与已经存在的供电站有相同的供电范围。

给你两个整数 r 和 k ,如果以最优策略建造额外的发电站,返回所有城市中,最小电量的最大值是多少。

这 k 座供电站可以建在多个城市。

示例 1:

输入:stations = [1,2,4,5,0], r = 1, k = 2
输出:5
解释:
最优方案之一是把 2 座供电站都建在城市 1 。
每座城市的供电站数目分别为 [1,4,4,5,0] 。
- 城市 0 的供电站数目为 1 + 4 = 5 。
- 城市 1 的供电站数目为 1 + 4 + 4 = 9 。
- 城市 2 的供电站数目为 4 + 4 + 5 = 13 。
- 城市 3 的供电站数目为 5 + 4 = 9 。
- 城市 4 的供电站数目为 5 + 0 = 5 。
供电站数目最少是 5 。
无法得到更优解,所以我们返回 5 。

示例 2:

输入:stations = [4,4,4,4], r = 0, k = 3
输出:4
解释:
无论如何安排,总有一座城市的供电站数目是 4 ,所以最优解是 4 。

提示:

  • n == stations.length
  • 1 <= n <= 10^5
  • 0 <= stations[i] <= 10^5
  • 0 <= r <= n - 1
  • 0 <= k <= 10^9

提示 1

Pre calculate the number of stations on each city using Line Sweep.


提示 2

Use binary search to maximize the minimum.

解法:二分 + 前缀和 + 差分 + 贪心

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

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

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

在哪建供电站最好呢?

提示 3
从左到右遍历,由于 i 左侧的电量都已处理完毕,所以在 i 右侧建供电站,所以贪心地在 i + r

处建供电站,由于不能超出数组下标范围,所以在 min(i+r,n−1) 处建是最合适的,恰好让 i 在新建供电站的覆盖范围的左边界上。此时新的供电站的覆盖范围为 (i, i + 2r ),考虑数组下标范围,即为( i, Math.min(i + 2r, n - 1))。

提示 4
假设 i + r 处需要建 m 个供电站才能补足 i 处的电量到minPower,那么需要把 [i,min(i + 2r,n−1)] 范围内的电量都增加 m,用差分数组来更新是最简单的。

最后判断总的需要新建的供电站数量是否超过 k,如果超过说明答案 minPower 偏大,否则说明偏小。

如果以上提示没看明白,请先做以下题目:

关于对差分数组的详细讲解:LeetCode 1094. 拼车-CSDN博客

与本题同类型题目的详细讲解:LeetCode 2772. 使数组中的所有元素都等于零-CSDN博客

Java版:

class Solution {
    public long maxPower(int[] stations, int r, int k) {
        int n = stations.length;
        long[] presum = new long[n + 1];
        long min = Long.MAX_VALUE;
        for (int i = 1; i <= n; i++) {
            presum[i] = presum[i - 1] + stations[i - 1];
        }
        // power[]数组记录每个城市的电量
        long[] power = new long[n];
        for (int i = 0; i < n; i++) {
            // [i - r, i + r] 范围内的供电站都给i处的城市供电
            power[i] = presum[Math.min(i + r + 1, n)] - presum[Math.max(i - r, 0)];
            min = Math.min(min, power[i]);
        }
        long left = min;
        long right = min + k;
        while (left <= right) {
            long mid = left + (right - left) / 2;
            if (check(mid, power, n, r, k)) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return right;
    }

    private boolean check(long minPower, long[] power, int n, int r, int k) {
        int need = 0;
        long sumD = 0;
        long[] diff = new long[n];
        for (int i = 0; i < n; i++) {
            // 累加差分值
            sumD += diff[i];
            long m = minPower - power[i] - sumD;
            if (m > 0) {
                // 需要新建m个供电站
                need += m;
                if (need > k) {
                    return false;
                }
                // 差分值更新
                sumD += m;
                if (i + 2 * r + 1 < n) {
                    diff[i + 2 * r + 1] -= m;
                } 
            } 
        }
        return true;
    }
}

Python3版:

标准数据类型

Python3 中常见的数据类型有:

  • Number(数字)
  • String(字符串)
  • bool(布尔类型)
  • List(列表)
  • Tuple(元组)
  • Set(集合)
  • Dictionary(字典)

Python3 的六个标准数据类型中:

  • 不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
  • 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。

此外还有一些高级的数据类型,如: 字节数组类型(bytes)。

Number(数字)

Python3 支持 int、float、bool、complex(复数)

在Python 3里,只有一种整数类型 int,表示为长整型,没有 python2 中的 Long。

class Solution:
    def maxPower(self, stations: List[int], r: int, k: int) -> int:
        n = len(stations)
        presum = [0] * (n + 1)
        for i in range(1, n + 1):
            presum[i] = presum[i - 1] + stations[i - 1]

        power = [0] * n
        for i in range(n):
            power[i] = presum[min(i + r + 1, n)] - presum[max(i - r, 0)]
        
        left = min(power)
        right = left + k
        while left <= right:
            mid = left + (right - left) // 2
            if self.check(mid, power, n, r, k):
                left = mid + 1
            else:
                right = mid - 1
        return right
    
    def check(self, minPower: int, power: List[int], n: int, r: int, k: int) -> bool:
        diff = [0] * n
        need = 0
        sumD = 0
        for i in range(n):
            sumD += diff[i]
            m = minPower - power[i] - sumD
            if m > 0:
                need += m
                if need > k:
                    return False
                sumD += m
                if i + 2 * r + 1 < n:
                    diff[i + 2 * r + 1] -= m
        return True
复杂度分析
  • 时间复杂度:O(nlogk),其中 n 为 stations 的长度。二分需要循环 O(logk) 次。总的时间复杂度O(n + n logk) = O(nlogk)
  • 空间复杂度:O(n)。

标签:stations,int,城市,min,2528,电量,供电站,LeetCode
From: https://blog.csdn.net/m0_56090828/article/details/140173895

相关文章

  • LeetCode-刷题记录-滑动窗口合集(本篇blog会持续更新哦~)
    一、滑动窗口概述滑动窗口(SlidingWindow)是一种用于解决数组(或字符串)中子数组(或子串)问题的有效算法。SlidingWindow核心思想:滑动窗口技术的基本思想是维护一个窗口(一般是一个子数组或子串),该窗口在数组上滑动,并在滑动过程中更新窗口的内容。通过滑动窗口,可以在(O(......
  • [Leetcode]Top 150
    链表旋转链表给你一个链表的头节点head,旋转链表,将链表每个节点向右移动k个位置。#Definitionforsingly-linkedlist.#classListNode:#def__init__(self,val=0,next=None):#self.val=val#self.next=nextclassSolution:defro......
  • 每日一题:Leetcode-102 二叉树的层序遍历
    力扣题目解题思路java代码力扣题目:给你二叉树的根节点 root ,返回其节点值的 层序遍历 。(即逐层地,从左到右访问所有节点)。示例1:输入:root=[3,9,20,null,null,15,7]输出:[[3],[9,20],[15,7]]示例2:输入:root=[1]输出:[[1]]示例3:输入:root=[]输出:[]......
  • 【LeetCode 0232】【设计】用FILO栈实现FIFO队列
    ImplementQueueusingStacksImplementafirstinfirstout(FIFO)queueusingonlytwostacks.Theimplementedqueueshouldsupportallthefunctionsofanormalqueue(push,peek,pop,andempty).ImplementtheMyQueueclass:*voidpush(intx)Pushes......
  • LeetCode 算法:路径总和 III c++
    原题链接......
  • 【LeetCode】力扣刷题记录第五天
    第五天!第一题:LeetCode1720 首先,我们先来读懂题目什么意思:encoded[i]=arr[i]XORarr[i+1]输入:encoded=[1,2,3],first=1输出:[1,0,2,1]解释:若arr=[1,0,2,1],那么first=1且encoded=[1XOR0,0XOR2,2XOR1]=[1,2,3]encode[i-1]=arr[i-1]XORarr[i......
  • [LeetCode] 45. Jump Game II
    有点意思,需要动态规划。fromtypingimportListfromcollectionsimportCounterimporttimeclassSolution:defjump(self,nums:List[int])->int:max_reachable=0min_steps=0fori,elementinenumerate(nums):i......
  • Leetcode秋招冲刺(专题13--15)
    专题13:广度优先搜索题目559:N叉树的最大深度(YES)解题思路:使用广度优先搜索,广度优先搜索的核心就是使用队列queue存储每个根节点,然后再存储孩子节点。给定一个N叉树,找到其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。N叉树输入按层序遍历序......
  • [LeetCode] 55. Jump Game
    写了一个符和直觉的递归,时间超限了。fromtypingimportListimporttimeclassSolution:defcanJump(self,nums:List[int])->bool:iflen(nums)==1:returnTruereturnself.isreach(nums,0)defisreach(self,nums:List[i......
  • 【Java完整版 面试必备】Leetcode Top100题目和答案-矩阵篇
    目录以下摘自leetcodeTop100精选题目-矩阵篇​矩阵置零螺旋矩阵旋转图像搜索二维矩阵II以下摘自leetcodeTop100精选题目-矩阵篇矩阵置零给定一个 mxn 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。示例:输入:matrix......