2111-使数组 K 递增的最少操作次数
给你一个下标从 0 开始包含 n
个正整数的数组 arr
,和一个正整数 k
。
如果对于每个满足 k <= i <= n-1
的下标 i
,都有 arr[i-k] <= arr[i]
,那么我们称 arr
是 K
递增 的。
- 比方说,
arr = [4, 1, 5, 2, 6, 2]
对于k = 2
是 K 递增的,因为:arr[0] <= arr[2] (4 <= 5)
arr[1] <= arr[3] (1 <= 2)
arr[2] <= arr[4] (5 <= 6)
arr[3] <= arr[5] (2 <= 2)
- 但是,相同的数组
arr
对于k = 1
不是 K 递增的(因为arr[0] > arr[1]
),对于k = 3
也不是 K 递增的(因为arr[0] > arr[3]
)。
每一次 操作 中,你可以选择一个下标 i
并将 arr[i]
**改成任意 **正整数。
请你返回对于给定的 k
,使数组变成 K 递增的 最少操作次数 。
示例 1:
**输入:** arr = [5,4,3,2,1], k = 1
**输出:** 4
**解释:** 对于 k = 1 ,数组最终必须变成非递减的。
可行的 K 递增结果数组为 [5, _ **6**_ , _ **7**_ , _ **8**_ , _ **9**_ ],[ _ **1**_ , _ **1**_ , _ **1**_ , _ **1**_ ,1],[ _ **2**_ , _ **2**_ ,3, _ **4**_ , _ **4**_ ] 。它们都需要 4 次操作。
次优解是将数组变成比方说 [ _ **6**_ , _ **7**_ , _ **8**_ , _ **9**_ , _ **10**_ ] ,因为需要 5 次操作。
显然我们无法使用少于 4 次操作将数组变成 K 递增的。
示例 2:
**输入:** arr = [4,1,5,2,6,2], k = 2
**输出:** 0
**解释:**
这是题目描述中的例子。
对于每个满足 2 <= i <= 5 的下标 i ,有 arr[i-2] <= **** arr[i] 。
由于给定数组已经是 K 递增的,我们不需要进行任何操作。
示例 3:
**输入:** arr = [4,1,5,2,6,2], k = 3
**输出:** 2
**解释:**
下标 3 和 5 是仅有的 3 <= i <= 5 且不满足 arr[i-3] <= arr[i] 的下标。
将数组变成 K 递增的方法之一是将 arr[3] 变为 4 ,且将 arr[5] 变成 5 。
数组变为 [4,1,5, _ **4**_ ,6, _ **5**_ ] 。
可能有其他方法将数组变为 K 递增的,但没有任何一种方法需要的操作次数小于 2 次。
提示:
1 <= arr.length <= 105
1 <= arr[i], k <= arr.length
方法一:动态规划
提示 1
题目的要求本质上是对于每一个 i~(0 \leq i < k),数组 arr 的子序列:
\textit{arr}[i], \textit{arr}[i + k], \textit{arr}[i + 2k], \cdots
是单调递增的。
提示 1 解释
由于 arr}[i - k] \leq \textit{arr}[i],它也可以写成 arr}[i] \leq \textit{arr}[i + k]。如果我们对于 arr}[i + k] 也套用这个不等式,就可以得到 arr}[i + k] \leq \textit{arr}[i + 2k]。以此类推,我们就可以得到:
\textit{arr}[i] \leq \textit{arr}[i + k] \leq \textit{arr}[i + 2k] \leq \cdots
也就是说,我们将数组 arr 中的每个元素根据其下标对 k 取模的值,分成了 k 个子序列(即下标对 k 取模的值分别为 0, 1, \cdots, k-1)。这 k-1 个子序列分别都是单调递增的。
提示 2
对于给定的一个序列,如果我们希望通过修改最少的元素,使得它单调递增,那么最少需要修改的元素个数,就是「序列的长度」减去「序列的最长递增子序列」的长度。
提示 2 解释
我们可以这样想:对于序列中那些需要被修改的元素,由于我们可以把它们修改成任意元素,因此它们修改之前的值并不重要,我们可以忽略它们。
而对于序列中那些没有被修改的元素,由于最终的序列是单调递增的,因此这些没有被修改的元素组成的子序列也一定是单调递增的。要想修改的元素越少,这个子序列就要越长。因此我们的目标就是求出序列的最长递增的子序列。
思路与算法
我们对于每一个满足 0 \leq i < k 的 i,抽取出数组 arr 的子序列:
\textit{arr}[i], \textit{arr}[i + k], \textit{arr}[i + 2k], \cdots
设其长度为 length,最长递增的子序列的长度为 f,那么最少需要修改的元素个数即为 length} - f。
最终的答案即为所有的 length} - f 之和。
细节
求解最长递增子序列可以参考「300. 最长递增子序列」的官方题解 的方法二,这里不再赘述。
代码
1 | class Solution { |
1 | class Solution: |
复杂度分析
时间复杂度:O(n \log \dfrac{n}{k})。每个序列的长度为 O(\dfrac{n}{k}),寻找其最长递增子序列需要的时间为 O(\dfrac{n}{k} \log \dfrac{n}{k}),而一共有 k 个序列,因此总时间复杂度为 O(n \log \dfrac{n}{k})。
空间复杂度:O(\dfrac{n}{k}),即为寻找单个序列的最长递增子序列时,数组 f 需要的空间。