LeetCode(354):俄羅斯套娃信封問題 Russian Doll Envelopes(Java)

2020.1.10 . LeetCode 從零單刷個人筆記整理(持續更新)

github:https://github.com/ChopinXBP/LeetCode-Babel

這道題是之前 LeetCode(300):最長上升子序列 Longest Increasing Subsequence(Java) 的拓展問題。對所有信封排序之後,原題相當於是二維的最長上升子序列。

思路主要有動態規劃和動態規劃+二分查找。

普通的動態規劃相當於是一個01揹包問題。建立dp數組,dp[i]代表包括第i+1封信,當前信封的最大嵌套數量。

每次第i封信的最大嵌套數量需要遍歷信件j=[0,i]保留最大值,動態轉移方程爲:

dp[i] = Math.max(dp[i], dp[j] + 1);

由於最大嵌套數量的信封不一定包括最後一封,因此需要全程取最大值。

動態規劃+二分查找的思路與最長上升子序列中的思路類似。


傳送門:俄羅斯套娃信封問題

You have a number of envelopes with widths and heights given as a pair of integers (w, h). One envelope can fit into another if and only if both the width and height of one envelope is greater than the width and height of the other envelope.

What is the maximum number of envelopes can you Russian doll? (put one inside other)

Note: Rotation is not allowed.

給定一些標記了寬度和高度的信封,寬度和高度以整數對形式 (w, h) 出現。當另一個信封的寬度和高度都比這個信封大的時候,這個信封就可以放進另一個信封裏,如同俄羅斯套娃一樣。

請計算最多能有多少個信封能組成一組“俄羅斯套娃”信封(即可以把一個信封放到另一個信封裏面)。

說明: 不允許旋轉信封。

示例:
輸入: envelopes = [[5,4],[6,4],[6,7],[2,3]]
輸出: 3 
解釋: 最多信封的個數爲 3, 組合爲: [2,3] => [5,4] => [6,7]。


import java.util.Arrays;

/**
 *
 * You have a number of envelopes with widths and heights given as a pair of integers (w, h).
 * One envelope can fit into another if and only if both the width and height of one envelope is greater than the width and height of the other envelope.
 * What is the maximum number of envelopes can you Russian doll? (put one inside other)
 * Note: Rotation is not allowed.
 * 給定一些標記了寬度和高度的信封,寬度和高度以整數對形式 (w, h) 出現。當另一個信封的寬度和高度都比這個信封大的時候,這個信封就可以放進另一個信封裏,如同俄羅斯套娃一樣。
 * 請計算最多能有多少個信封能組成一組“俄羅斯套娃”信封(即可以把一個信封放到另一個信封裏面)。
 * 說明: 不允許旋轉信封。
 *
 */

public class RussianDollEnvelopes {
    //動態規劃
    public int maxEnvelopes(int[][] envelopes) {
        Arrays.sort(envelopes, (a, b)->a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
        int[] dp = new int[envelopes.length];
        Arrays.fill(dp, 1);
        int result = 0;
        for(int i = 0; i < envelopes.length; i++) {
            for(int j = 0; j < i; j++) {
                if(envelopes[i][0] > envelopes[j][0] && envelopes[i][1] > envelopes[j][1]){
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            result = Math.max(dp[i], result);
        }
        return result;
    }

    //動態規劃+二分查找
    public int maxEnvelopes2(int[][] envelopes) {
        int len = envelopes.length;
        if (len < 2) {
            return len;
        }
        Arrays.sort(envelopes, (a, b)->a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);

        int[] tail = new int[len];
        tail[0] = envelopes[0][1];
        // end 表示有序數組 tail 的最後一個已經賦值元素的索引
        int end = 0;

        for (int i = 1; i < len; i++) {
            int target = envelopes[i][1];

            if (target > tail[end]) {
                end++;
                tail[end] = target;
            } else {
                int left = 0;
                int right = end;

                while (left < right) {
                    int mid = (left + right) >>> 1;
                    if (tail[mid] < target) {
                        left = mid + 1;
                    } else {
                        right = mid;
                    }
                }
                tail[left] = target;
            }
        }
        return end + 1;
    }
}




#Coding一小時,Copying一秒鐘。留個言點個讚唄,謝謝你#

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章