1. 程式人生 > 其它 >646. 最長數對鏈(動態規劃)

646. 最長數對鏈(動態規劃)

技術標籤:力扣

646. 最長數對鏈

題目

給出 n 個數對。 在每一個數對中,第一個數字總是比第二個數字小。

現在,我們定義一種跟隨關係,當且僅當 b < c 時,數對(c, d) 才可以跟在 (a, b) 後面。我們用這種形式來構造一個數對鏈。

給定一個數對集合,找出能夠形成的最長數對鏈的長度。你不需要用到所有的數對,你可以以任何順序選擇其中的一些數對來構造。

在這裡插入圖片描述

提示:

  • 給出數對的個數在 [1, 1000] 範圍內。

解題思路

這題其實借用了 354.俄羅斯套娃信封問題的思想。我們需要對這個二維陣列的開始值進行升序排序,如果遇到相同的,就按照結束值進行降序排序,然後就得到了一個排序後的陣列。

我們這裡就可以用300.最長遞增子序列的方法來求出結果了。

需要注意的是if判斷那一塊:要注意用前一個的結束和後一個的開始去進行比較。因為這個單獨抽離成一個一維陣列比較麻煩,所以直接在這裡用這種方式進行比較。

 /*用nums當前的開始去比較nums之前的 結束 。
	[[1,2],[3,4]] 這就相當於用3去和2比較
*/
if (nums[j][1] < nums[i][0]) {
     dp[i] = Math.max(dp[i], dp[j] + 1);
     }

程式碼

class Solution {
        public int findLongestChain
(int[][] pairs) { int N = pairs.length; if (N == 0) { return 0; } Arrays.sort(pairs, new Comparator<int[]>() { //按照每個區間的開始進行升序排列,若開始一樣,則按結束降序排列 public int compare(int[] a, int[] b) { /* a[0]、b[0]分別代表前一個、後一個數組的開始 a[1]、b[1]分別代表前一個、後一個數組的結束 */
return a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]; } }); return lengthOfLIS(pairs); } //用來求最長遞增子序列。這裡稍微修改一下作為輔助方法 public int lengthOfLIS(int[][] nums) { if (nums.length == 0) { return 0; } int N = nums.length; //dp[i]存放的是:以nums[i]結尾的最長遞增子序列的長度 int[] dp = new int[N]; //base case:將dp[]都初始化為1 Arrays.fill(dp, 1); for (int i = 0; i < N; i++) {//i=N-1就是dp[]的最後一個元素了,原為dp[]的長度和nums[]的相同 for (int j = 0; j < i; j++) { /*用nums當前的開始去比較nums之前的 結束 假設有[[1,2],[3,4]] 這就相當於用3去和2比較 */ if (nums[j][1] < nums[i][0]) { dp[i] = Math.max(dp[i], dp[j] + 1); } } } int res = 0; //來遍歷一次經過整理的dp[],找出最大值 for (int i = 0; i < dp.length; i++) { res = Math.max(res, dp[i]); } return res; } }