使数组 K 递增的最少操作次数
难度:
标签:
题目描述
代码结果
运行时间: 162 ms, 内存: 27.3 MB
/*
* 思路:
* 1. 使用 Java Stream API 实现相同的逻辑。
* 2. 我们可以使用 stream 进行集合操作,
* 然后使用 Collectors 和其他终止操作来实现功能。
*/
import java.util.*;
import java.util.stream.*;
public int minOperationsStream(int[] arr, int k) {
int n = arr.length;
return IntStream.range(0, k).map(i -> {
List<Integer> seq = IntStream.range(i, n).filter(j -> j % k == 0)
.mapToObj(j -> arr[j]).collect(Collectors.toList());
return seq.size() - lengthOfLIS(seq);
}).sum();
}
private int lengthOfLIS(List<Integer> seq) {
List<Integer> lis = new ArrayList<>();
for (int num : seq) {
int idx = Collections.binarySearch(lis, num);
if (idx < 0) idx = -(idx + 1);
if (idx < lis.size()) lis.set(idx, num);
else lis.add(num);
}
return lis.size();
}
解释
方法:
本题解使用了最长递增子序列(LIS)的思想来解决问题。首先,对于每个下标 i(i < k),我们考虑以 i 为起点,间隔为 k 的子序列,这样可以得到 k 个子序列。对每个子序列,我们使用二分查找法求出其最长递增子序列的长度。由于我们需要将子序列变为递增,所以需要进行的操作次数等于子序列的长度减去其最长递增子序列的长度。最后,将所有子序列需要的操作次数相加,即为最终答案。
时间复杂度:
O(n * log(n/k))
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在处理这个问题时选择将原数组分解为k个子序列,而不是整个数组进行一次操作?
▷🦆
在使用二分查找法来确定最长递增子序列长度时,为什么替换时选择更新t数组中的元素而不是只进行添加操作?
▷🦆
你是如何保证在每个子序列中应用最长递增子序列方法能够满足整个数组的K递增条件的?
▷🦆
在实际操作中,如果数组的长度n不是k的整数倍,如何处理最后不完全的子序列?
▷