使数组变美的最小增量运算数(线性dp)

给你一个下标从\(0\)开始、长度为\(n\)的整数数组\(nums\),和一个整数\(k\)

你可以执行下述递增运算任意次(可以是\(0\)次):

从范围\([0, n - 1]\)中选择一个下标\(i\),并将\(nums[i]\)的值加\(1\)
如果数组中任何长度大于或等于\(3\)的子数组,其最大元素都大于或等于\(k\),则认为数组是一个美丽数组。
以整数形式返回使数组变为美丽数组需要执行的最小递增运算数。
子数组是数组中的一个连续非空元素序列。

示例 1:

输入:nums = [2,3,0,0,2], k = 4
输出:3
解释:可以执行下述递增运算,使 nums 变为美丽数组:
选择下标 i = 1 ,并且将 nums[1] 的值加 1 -> [2,4,0,0,2] 。
选择下标 i = 4 ,并且将 nums[4] 的值加 1 -> [2,4,0,0,3] 。
选择下标 i = 4 ,并且将 nums[4] 的值加 1 -> [2,4,0,0,4] 。
长度大于或等于 3 的子数组为 [2,4,0], [4,0,0], [0,0,4], [2,4,0,0], [4,0,0,4], [2,4,0,0,4] 。
在所有子数组中,最大元素都等于 k = 4 ,所以 nums 现在是美丽数组。
可以证明无法用少于 3 次递增运算使 nums 变为美丽数组。
因此,答案为 3 。
示例 2:

输入:nums = [0,1,3,3], k = 5
输出:2
解释:可以执行下述递增运算,使 nums 变为美丽数组:
选择下标 i = 2 ,并且将 nums[2] 的值加 1 -> [0,1,4,3] 。
选择下标 i = 2 ,并且将 nums[2] 的值加 1 -> [0,1,5,3] 。
长度大于或等于 3 的子数组为 [0,1,5]、[1,5,3]、[0,1,5,3] 。
在所有子数组中,最大元素都等于 k = 5 ,所以 nums 现在是美丽数组。
可以证明无法用少于 2 次递增运算使 nums 变为美丽数组。
因此,答案为 2 。
示例 3:

输入:nums = [1,1,2], k = 1
输出:0
解释:在这个示例中,只有一个长度大于或等于 3 的子数组 [1,1,2] 。
其最大元素 2 已经大于 k = 1 ,所以无需执行任何增量运算。
因此,答案为 0 。

提示:

3 <= n == nums.length <= 1e5
0 <= nums[i] <= 1e9
0 <= k <= 1e9
这个是dp

思路:
创建一个大小为 n(其中 n 为 nums 的大小)的 dp 数组,\(dp[i]\)表示修改第\(i\)项并使前\(i\)项变为美丽数组的最小修改次数。那么可以得到状态转移方程:

\[dp[i]=min{dp[i−3],dp[i−2],dp[i−1]}+max{0,k−nums[i]} \]

边界处理:当 i<3 时,\(dp[i]=max{0,  k−nums[i]}\)

使原数组变为美丽数组的最小修改次数\(ans=min{dp[n−3],dp[n−2],dp[n−1]}\)

class Solution {
public:
    long long minIncrementOperations(vector<int>& nums, int k) {
        int n = nums.size();
        long long dp[10000000];
        dp[0] = max(0, k - nums[0]);
        dp[1] = max(0, k - nums[1]);
        dp[2] = max(0, k - nums[2]);
        for(int i = 3; i < n; i++)
        {
            dp[i] = max(0, k - nums[i]) + min({dp[i - 1], dp[i - 2], dp[i - 3]});
        }

        return min({dp[n - 1], dp[n - 2], dp[n - 3]});
    }
};

posted @ 2023-11-02 20:03  lipu123  阅读(30)  评论(0)    收藏  举报