https://leetcode-cn.com/problems/make-array-strictly-increasing/solution/dp-on2-by-mike-meng/
给你两个整数数组arr1
和arr2
,返回使arr1
严格递增所需要的最小「操作」数(可能为 0)。每一步「操作」中,你可以分别从 arr1
和 arr2
中各选出一个索引,分别为 i
和 j
,0 <= i < arr1.length
和 0 <= j < arr2.length
,然后进行赋值运算 arr1[i] = arr2[j]
。如果无法让 arr1
严格递增,请返回 -1
。
1 <= arr1.length, arr2.length <= 2000
0 <= arr1[i], arr2[i] <= 10^9
输入:arr1 = [1,5,3,6,7], arr2 = [1,3,2,4]
输出:1
解释:用 2 来替换 5,之后 arr1 = [1, 2, 3, 6, 7]。
输入:arr1 = [1,5,3,6,7], arr2 = [4,3,1]
输出:2
解释:用 3 来替换 5,然后用 4 来替换 3,得到 arr1 = [1, 3, 4, 6, 7]。
输入:arr1 = [1,5,3,6,7], arr2 = [1,6,3,3]
输出:-1
解释:无法使 arr1 严格递增。
首先定义dp[i][j]
代表的是前j
个元素经过i
次变换后按数组严格递增后,第j个元素的最小值。那么dp[i][j]
有2种可能递推:
arr[j] > dp[i][j - 1]
,也就是已经和前面形成严格递增了,那么dp[i][j] = arr[j]
了。tmp = upper_bound(arr2,0,arr.length,dp[i-1][j-1])
,为什么是dp[i-1][j-1]
呢?因为当前值j
要经历一次转换所以i-1 +1
,所以这时候dp[i][j] = Math.min(dp[i][j],tmp)
了。import java.util.Arrays;
public class test4 {
public int upperBound(int arr[],int l,int r,int key)
{
while (l <= r)
{
int mid =(l + r) / 2;
if(arr[mid] <= key)
{
l = mid + 1;
}
else
{
r = mid - 1;
}
}
if(l >= arr.length||arr[l] <= key) return Integer.MAX_VALUE;//无效值
return arr[l];
}
public int makeArrayIncreasing(int[] arr1, int[] arr2) {
int ans = -1;
if(arr1 == null||arr2 == null || arr1.length == 0 || arr2.length == 0) return ans;
int length = arr1.length;
int dp[][] = new int[length + 1][length + 1];
for(int i = 0; i < length + 1;i++) Arrays.fill(dp[i],Integer.MAX_VALUE);
dp[0][0] = -1;
// 排序
Arrays.sort(arr2);
for(int i = 1;i <= length;i++)
{
// 当前数字
int index = i - 1;
for(int j = 0; j <= i;j++)
{
if(arr1[index] > dp[j][i - 1])
{
dp[j][i] = arr1[index];
}
if(j > 0)
{
int tmp = upperBound(arr2,0,arr2.length - 1,dp[j - 1][i - 1]);
dp[j][i] = Math.min(dp[j][i],tmp);
}
if(i == length && dp[j][i] != Integer.MAX_VALUE)
{
return j;
}
}
}
return -1;
}
public static void main(String[] args) {
int arr1[] = {1,5,3,6,7};
int arr2[] = {1,6,3,3};
int arr3[] = {1,2,3,4};
test4 of = new test4();
System.out.println(of.makeArrayIncreasing(arr1,arr2));
//System.out.println(of.upperBound(arr3,0,arr3.length - 1,-2));
}
}