使数组严格递增
难度:
标签:
题目描述
代码结果
运行时间: 127 ms, 内存: 16.6 MB
/*
* Problem: Given two integer arrays arr1 and arr2, return the minimum number of operations required to make arr1 strictly increasing by replacing elements from arr1 with elements from arr2. If it is impossible, return -1.
* Approach: Use dynamic programming and Java Streams to process the arrays and keep track of the minimum operations required for each possible ending value of arr1 up to each index.
*/
import java.util.Arrays;
import java.util.stream.IntStream;
public class Solution {
public int makeArrayIncreasing(int[] arr1, int[] arr2) {
Arrays.sort(arr2);
int n = arr1.length;
int m = arr2.length;
int[][] dp = new int[n + 1][m + 1];
for (int[] row : dp) Arrays.fill(row, Integer.MAX_VALUE);
dp[0][0] = 0;
IntStream.range(1, n + 1).forEach(i -> {
IntStream.rangeClosed(0, m).forEach(j -> {
if (j == 0 || arr2[j - 1] < arr1[i - 1]) {
dp[i][0] = Math.min(dp[i][0], dp[i - 1][j]);
}
if (j > 0 && arr2[j - 1] < arr1[i - 1]) {
dp[i][j] = Math.min(dp[i][j], dp[i - 1][0] + 1);
}
if (j > 0 && arr2[j - 1] < arr2[j - 2]) {
dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - 1] + 1);
}
});
});
return IntStream.rangeClosed(0, m).map(j -> dp[n][j]).min().orElse(Integer.MAX_VALUE) == Integer.MAX_VALUE ? -1 : IntStream.rangeClosed(0, m).map(j -> dp[n][j]).min().orElse(Integer.MAX_VALUE);
}
}
解释
方法:
这个题解使用了动态规划和二分查找。具体思路是:对于 arr1 的每个位置 i,考虑是否替换 arr1[i] 以及替换成 arr2 中的哪个元素。通过递归函数 dfs(i) 来计算arr1[0:i+1] 变为严格递增序列所需的最小替换次数。
在 dfs(i) 中,首先用二分查找找到 arr2 中严格大于 arr1[i] 的最小元素的下标 k。然后比较两种可能性:
1. 不替换 arr1[i],只需 arr1[i-1] < arr1[i],这种情况下替换次数为 dfs(i-1)。
2. 替换 arr1[i],需要枚举替换的起始位置 j,满足 j < i-1 且 arr2[k-(i-j-1)] > arr1[j],即用arr2[k-(i-j-1):k] 替换 arr1[j+1:i],这种情况下替换次数为 dfs(j)+i-j-1。最后取所有可能性的最小值。
通过添加 @cache 装饰器来缓存dfs结果,避免重复计算。如果最终 dfs(n) < n(n为数组长度),则说明可以得到严格递增序列,返回替换次数 n-dfs(n),否则返回-1。
时间复杂度:
O(n * min(n, m) * log m)
空间复杂度:
O(n + m)
代码细节讲解
🦆
为什么在动态规划的状态转移过程中考虑两种情况:不替换当前元素和替换当前元素?这样的分类有什么优势?
▷🦆
在递归函数dfs中,为什么需要使用二分查找来确定arr2中严格大于arr1[i]的最小元素?这对算法的效率提升有何帮助?
▷🦆
题解中提到的枚举替换起始位置j的逻辑,为何要确保j小于i-1并且arr2[k-(i-j-1)] > arr1[j]?这样的条件设置是基于什么考虑?
▷🦆
在处理边界情况时,如何确保算法在arr1或arr2为空时仍然能正确运行?
▷