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 相關知識】,並且【短時間在面試方面有跨越式提升】
面試路上,你不孤單!