『Leetcode 1187』使数组严格递增

『参考』:

https://leetcode-cn.com/problems/make-array-strictly-increasing/solution/dp-on2-by-mike-meng/

『题目』:

 给你两个整数数组arr1arr2,返回使arr1 严格递增所需要的最小「操作」数(可能为 0)。每一步「操作」中,你可以分别从 arr1arr2 中各选出一个索引,分别为 ij0 <= i < arr1.length0 <= 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种可能递推:

  1. 假如当前的arr[j] > dp[i][j - 1],也就是已经和前面形成严格递增了,那么dp[i][j] = arr[j]了。
  2. 假如当前的值不管如何都换一下,最后的情况还是找一个比前面大一丢丢的值,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));
    }

}

你可能感兴趣的:(『数据结构与算法』)