1526. 形成目标数组的子数组最少增加次数
大约 3 分钟
---
1526. 形成目标数组的子数组最少增加次数
- 标签:栈、贪心、数组、动态规划、单调栈
- 难度:困难
题目链接
题目大意
描述:给定一个目标数组 。初始数组全为 ,长度与 相同。每次操作可以将一个连续子数组中的所有元素加 。
要求:返回将初始数组变为 所需的最少操作次数。
说明:
- 。
- 。
示例:
- 示例 1:
输入:target = [1,2,3,2,1]
输出:3
解释:我们需要至少 3 次操作从 intial 数组得到 target 数组。
[0,0,0,0,0] 将下标为 0 到 4 的元素(包含二者)加 1 。
[1,1,1,1,1] 将下标为 1 到 3 的元素(包含二者)加 1 。
[1,2,2,2,1] 将下标为 2 的元素增加 1 。
[1,2,3,2,1] 得到了目标数组。- 示例 2:
输入:target = [3,1,1,2]
输出:4
解释:(initial)[0,0,0,0] -> [1,1,1,1] -> [1,1,1,2] -> [2,1,1,2] -> [3,1,1,2] (target) 。解题思路
思路 1:贪心(相邻差分)
1. 核心思想
每次操作选择一个区间 ,等价于在差分视角下:
- 初始数组全 。
- 要使每个位置达到 ,需要加的操作总数是 。
关键:从 到 的变化量。如果 ,需要新开始 次操作(即左端点)。如果 ,则可以利用前面的操作延续。
因此最少操作次数 = 。
这个公式的直观理解:每个上升沿需要开启新的操作,下降沿自动结束操作。
2. 具体步骤
第 1 步:初始化 。
第 2 步:遍历 :
- 如果 ,。
第 3 步:返回 。
3. 正确性证明
- 差分数组 ,()。
- 每次区间加 等价于 ,。
- 最终每个 都需要一个对应的左端点操作。
- 因此总操作数 = (只计正数)= 。
4. 举例说明
以 为例:
- 。
- :,,。
- :,,。
- :,不变。
- :,不变。
。
操作方案:
- 加 →
- 加 →
- 加 →
等等,还不对。检查: - 加 →
- 加 →
这需要 步(全局 ,然后 加 , 加 )。对,是 步。
思路 1:代码
class Solution:
def minNumberOperations(self, target: List[int]) -> int:
ans = target[0]
for i in range(1, len(target)):
if target[i] > target[i - 1]:
ans += target[i] - target[i - 1]
return ans思路 1:复杂度分析
- 时间复杂度:。
- 空间复杂度:。