LeetCode56.合併區間、354. 俄羅斯套娃信封問題(合併區間進階)

LeetCode56.合併區間

【題目】

給出一個區間的集合,請合併所有重疊的區間。

【示例】

輸入: [[1,3],[2,6],[8,10],[15,18]]
輸出: [[1,6],[8,10],[15,18]]
解釋: 區間 [1,3][2,6] 重疊, 將它們合併爲 [1,6].

【思考】

本身思路很簡單,但是需要注意區間與區間的各種包含和交叉關係,最明顯的一點就是區間不一定是有序的。

所以需要先排序(根據第一個區間的第一個值排序),然後第二個區間的下標0的值小於第二個區間下標1的值的區間進行合併

排序使用sort並自定義排序方式:
這裏使用的是lamda簡化自定義排序方式

Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);

假設傳來兩個值,v1 與 v2,那麼他們的先後順序以 v1[0] 比 v2[0] 的結果爲準,即:若 v1[0] < v2[0] 則 v1 < v2,若 = 則 =,若 > 則 >

舉一反三:

Arrays.sort(intervals, (v1, v2) -> v1[0] == v2[0] ? v2[1] - v1[1] : v1[0] - v2[0]); 

表示:傳來兩個值 v1 與 v2,若 [0] 相同,則按 [1] 降序;若不同則按 [0] 升序。

【代碼】

package LeetCode;

import java.util.ArrayList;
import java.util.Arrays;

public class LeetCode56 {
    public int[][] merge(int[][] intervals) {
        if (intervals==null || intervals.length==0 || intervals[0].length==0)
            return new int[0][0];

        if (intervals.length==1) return intervals;
        int m,i,j;
        m = intervals.length;
        Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);
        ArrayList<int[]> paths = new ArrayList<>();

        i = 0;
        while (i < m) {
            int[] cur = new int[2];
            cur[0] = intervals[i][0];
            cur[1] = intervals[i][1];
            j=i+1;
            while (j<m && intervals[j][0]<=cur[1] && intervals[j][1]>=cur[0]) {
                cur[0] = Math.min(cur[0],intervals[j][0]);
                cur[1] = Math.max(cur[1],intervals[j][1]);
                j++;
            }
            paths.add(cur);
            i = j;
        }

        int[][] res = new int[paths.size()][2];
        for (i=0; i<paths.size(); i++) {
            res[i] = paths.get(i);
        }

        return res;
    }

    public static void main(String[] args) {
        int[][] a = {{1,3},{2,6},{8,10},{15,18}};
        int[][] list = new LeetCode56().merge(a);
        System.out.println(list);
        System.out.println();
    }
}


354. 俄羅斯套娃信封問題

【題目】

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

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

說明:
不允許旋轉信封。

【示例】

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

【思考】

這道題目其實是最長遞增子序列(Longes Increasing Subsequence,簡寫爲 LIS)的一個變種,因爲很顯然,每次合法的嵌套是大的套小的,相當於找一個最長遞增的子序列,其長度就是最多能嵌套的信封個數。

但是難點在於,標準的 LIS 算法只能在數組中尋找最長子序列,而我們的信封是由 (w, h) 這樣的二維數對形式表示的,如何把 LIS 算法運用過來呢?

這道題的解法是比較巧妙的:先對寬度 w 進行升序排序,如果遇到 w 相同的情況,則按照高度 h 降序排序。之後把所有的 h 作爲一個數組,在這個數組上計算 LIS 的長度就是答案。

在這裏插入圖片描述

在這裏插入圖片描述

所以這道題的關鍵就變成對這個二維數組排序:

方式一:使用Arrays.sort函數並重寫排序Comparator接口

Arrays.sort(envelopes, new Comparator<int[]>() 
    {
        public int compare(int[] a, int[] b) {
            return a[0] == b[0] ? 
                b[1] - a[1] : a[0] - b[0];
        }
    });

方式二:使用lamda語法簡化代碼:

// lamda實現自定義比較接口,先以v[0]升序,如果v[0]相同,在於v[1]降序
        Arrays.sort(envelopes,(v1,v2)->
                v1[0]==v2[0]?v2[1]-v1[1]:v1[0]-v2[0]);

【代碼】

package LeetCode;

import java.util.Arrays;

public class LeetCode354 {
    public int maxEnvelopes(int[][] envelopes) {
        if (envelopes==null || envelopes.length==0 || envelopes[0].length==0)
            return 0;

        int m,i,l,j;
        m = envelopes.length;
        // lamda實現自定義比較接口,先以v[0]升序,如果v[0]相同,在於v[1]降序
        Arrays.sort(envelopes,(v1,v2)->
                v1[0]==v2[0]?v2[1]-v1[1]:v1[0]-v2[0]);

        int[] dp = new int[m];

        Arrays.fill(dp,1);

        for (i=1; i<m; i++) {
            l = 0;
            for (j=0; j<i; j++) {
                if (envelopes[j][1]<envelopes[i][1]
                    && l < dp[j]) {
                    l = dp[j];
                }
            }
            dp[i] = l+1;
        }

        l = 0;
        for (i=0; i<m; i++) {
            if (l<dp[i]) l = dp[i];
        }

        return l;
    }

    public static void main(String[] args) {
        int[][] a = {{5,4},{6,4},{6,7},{2,3}};
        System.out.println(new LeetCode354().maxEnvelopes(a));
    }

}


【Java 面試那點事】

這裏致力於分享 Java 面試路上的各種知識,無論是技術還是經驗,你需要的這裏都有!

這裏可以讓你【快速瞭解 Java 相關知識】,並且【短時間在面試方面有跨越式提升】

面試路上,你不孤單!
在這裏插入圖片描述

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