JAVA 프로그램 설계: 배열을 엄격하게 증가(LeetCode:1187)

1943 단어
두 개의 정수 그룹arr1과arr2를 주고,arr1을 엄격하게 증가시키는 데 필요한 최소 '조작' 수를 되돌려줍니다. (0일 수도 있습니다.)
매 단계 "조작"에서, 너는 각각arr1과arr2에서 각각 색인을 선택할 수 있다. 각각 i와 j, 0 <=i arr1을 엄격하게 늘릴 수 없으면 -1로 돌아가십시오.
 
예 1:
입력:arr1=[1,5,3,6,7],arr2=[1,3,2,4] 출력:1 해석:2로 5를 바꾸고,그 다음에arr1=[1,2,3,6,7].예 2:
입력:arr1=[1,5,3,6,7],arr2=[4,3,1] 출력:2 해석:3으로 5를 교체한 다음에 4로 3을 교체하고arr1=[1,3,4,6,7]을 얻는다.예 3:
입력:arr1 = [1,5,3,6,7],arr2 = [1,6,3] 출력:-1 해석:arr1을 엄격하게 증가시킬 수 없습니다. 
팁:
1 <= arr1.length, arr2.length <= 2000 0 <= arr1[i], arr2[i] <= 10^9
사고방식: dp[i][j]를 정의하여 전 i개수가 j회 이후의 마지막 값을 대체하는 최소값을 나타낸다.복잡도 O (n^2logm)
class Solution {

    final static int inf = Integer.MAX_VALUE;

    public int makeArrayIncreasing(int[] arr1, int[] arr2) {

        int n = arr1.length;
        int m = arr2.length;
        int[][] dp = new int[n + 1][n + 1];

        for (int i = 0; i <= n; i++)
            Arrays.fill(dp[i], inf);

        Arrays.sort(arr2);

        dp[0][0] = -1;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= i; j++) {
                if (arr1[i - 1] > dp[i - 1][j])
                    dp[i][j] = arr1[i - 1];
                if (j > 0) {
                    int p = find(arr2, dp[i - 1][j - 1]);
                    if (p < m) dp[i][j] = Math.min(dp[i][j], arr2[p]);
                }
            }
        }

        for (int j = 0; j <= n; j++)
            if (dp[n][j] != inf)
                return j;

        return -1;

    }

    private int find(int[] arr, int val) {

        int l = 0, r = arr.length;
        while (l < r) {
            int mid = (l + r) / 2;
            if (arr[mid] > val)
                r = mid;
            else
                l = mid + 1;
        }

        return r;

    }
}

좋은 웹페이지 즐겨찾기