leetcode
leetcode 2451 ~ 2500
使数组变美的最小增量运算数

使数组变美的最小增量运算数

难度:

标签:

题目描述

You are given a 0-indexed integer array nums having length n, and an integer k.

You can perform the following increment operation any number of times (including zero):

  • Choose an index i in the range [0, n - 1], and increase nums[i] by 1.

An array is considered beautiful if, for any subarray with a size of 3 or more, its maximum element is greater than or equal to k.

Return an integer denoting the minimum number of increment operations needed to make nums beautiful.

A subarray is a contiguous non-empty sequence of elements within an array.

 

Example 1:

Input: nums = [2,3,0,0,2], k = 4
Output: 3
Explanation: We can perform the following increment operations to make nums beautiful:
Choose index i = 1 and increase nums[1] by 1 -> [2,4,0,0,2].
Choose index i = 4 and increase nums[4] by 1 -> [2,4,0,0,3].
Choose index i = 4 and increase nums[4] by 1 -> [2,4,0,0,4].
The subarrays with a size of 3 or more are: [2,4,0], [4,0,0], [0,0,4], [2,4,0,0], [4,0,0,4], [2,4,0,0,4].
In all the subarrays, the maximum element is equal to k = 4, so nums is now beautiful.
It can be shown that nums cannot be made beautiful with fewer than 3 increment operations.
Hence, the answer is 3.

Example 2:

Input: nums = [0,1,3,3], k = 5
Output: 2
Explanation: We can perform the following increment operations to make nums beautiful:
Choose index i = 2 and increase nums[2] by 1 -> [0,1,4,3].
Choose index i = 2 and increase nums[2] by 1 -> [0,1,5,3].
The subarrays with a size of 3 or more are: [0,1,5], [1,5,3], [0,1,5,3].
In all the subarrays, the maximum element is equal to k = 5, so nums is now beautiful.
It can be shown that nums cannot be made beautiful with fewer than 2 increment operations.
Hence, the answer is 2.

Example 3:

Input: nums = [1,1,2], k = 1
Output: 0
Explanation: The only subarray with a size of 3 or more in this example is [1,1,2].
The maximum element, 2, is already greater than k = 1, so we don't need any increment operation.
Hence, the answer is 0.

 

Constraints:

  • 3 <= n == nums.length <= 105
  • 0 <= nums[i] <= 109
  • 0 <= k <= 109

代码结果

运行时间: 145 ms, 内存: 30.0 MB


/*
题目思路:
使用 Java Stream API 可以更简洁地解决这个问题。通过使用 map 操作,将小于 k 的元素增加到 k,同时计算增加的次数。
*/

import java.util.Arrays;

public class Solution {
    public int minIncrements(int[] nums, int k) {
        return Arrays.stream(nums)
                     .map(num -> num < k ? k - num : 0)
                     .sum();
    }
}

解释

方法:

这道题的解法使用了动态规划的思想。设f[i]表示使得以索引i结尾的,长度至少为3的所有子数组的最大值都至少为k的最小增量操作数。初始时,f[0]、f[1]、f[2]分别计算nums数组前三个元素与k的差值,若已经大于或等于k则为0。对于每一个后续的元素x,计算使得x大于等于k所需的增量t。然后更新f[2]为t加上前三个f中的最小值(这确保任意长度大于等于3的子数组的最大值都大于等于k),并将f[0]、f[1]向前推进一位。最终,最小的f值即为所求答案,因为它表示的是数组最后三个元素满足条件的最小操作数。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
如何确保动态规划数组f[i]中的值能正确表示以i结尾的所有子数组长度大于等于3时的最小增量操作数?
在这个动态规划解法中,f[i]表示的是使得以索引i结尾的、长度至少为3的所有子数组的最大值都至少为k的最小增量操作数。这一值是通过结合当前元素到达k需要的增量与前三个元素中存储的最小操作数来更新的,确保任意长度大于等于3的子数组的最大值都至少为k。这样,通过持续更新这三个状态,可以确保每一次迭代后,f[i]都能正确地反映出以当前元素结尾的、满足条件的子数组的最小操作数。
🦆
为什么在动态规划更新过程中,只需要考虑前三个f值(f0, f1, f2)?这样的更新是否能覆盖所有的子数组情况?
因为题目要求的是长度至少为3的子数组,所以在更新每个f[i]时,只需考虑以当前元素为结尾且长度至少为3的子数组。这样的设计通过每次只保留最近三个f值,并将当前元素与这三个值结合更新,保证了任何长度大于等于3的子数组的最大值都能满足条件。这三个值足以覆盖所有长度大于等于3的子数组的情况,因为任何更长的子数组的最小操作数也会在这三个值中反映。
🦆
在动态规划的实现中,如果数组长度小于3,这种方法是否还适用?如何处理这种边界情况?
如果数组长度小于3,那么不存在长度至少为3的子数组,因此按照题目的要求,没有必要执行任何操作。在这种情况下,可以在动态规划算法的开始部分加入一个检查,如果数组长度小于3,则直接返回0,因为不需要任何增量操作。
🦆
动态规划解法中使用min函数来选择最小值,这种选择机制的正确性依据是什么?
使用min函数选择最小值的原因是,我们希望最小化整个数组满足条件的总增量操作数。通过选择前三个f值中的最小值并结合当前元素所需的最小增量,可以保证以当前元素结尾的、长度至少为3的子数组在增量操作尽可能小的情况下满足最大值至少为k的条件。这种方法确保了我们总是选择最优的(即成本最低的)操作策略来更新动态规划的状态。

相关问题