1. 程式人生 > >[LeetCode] Maximum Length of Pair Chain 鏈對的最大長度

[LeetCode] Maximum Length of Pair Chain 鏈對的最大長度

You are given n pairs of numbers. In every pair, the first number is always smaller than the second number.

Now, we define a pair (c, d) can follow another pair (a, b) if and only if b < c. Chain of pairs can be formed in this fashion.

Given a set of pairs, find the length longest chain which can be formed. You needn't use up all the given pairs. You can select pairs in any order.

Example 1:

Input: [[1,2], [2,3], [3,4]]
Output: 2
Explanation: The longest chain is [1,2] -> [3,4]

Note:

  1. The number of given pairs will be in the range [1, 1000].

這道題給了我們一些鏈對,規定了如果後面鏈對的首元素大於前鏈對的末元素,那麼這兩個鏈對就可以鏈起來,問我們最大能鏈多少個。那麼我們想,由於規定了鏈對的首元素一定小於尾元素,我們需要比較的是某個連結串列的首元素和另一個連結串列的尾元素之間的關係,如果整個鏈對陣列是無序的,那麼就很麻煩,所以我們需要做的是首先對鏈對陣列進行排序,按鏈對的尾元素進行排序,小的放前面。這樣我們就可以利用Greedy演算法進行求解了。我們可以用一個棧,先將第一個鏈對壓入棧,然後對於後面遍歷到的每一個鏈對,我們看其首元素是否大於棧頂鏈對的尾元素,如果大於的話,就將當前鏈對壓入棧,這樣最後我們返回棧中元素的個數即可,參見程式碼如下:

解法一:

class Solution {
public:
    int findLongestChain(vector<vector<int>>& pairs) {
        stack<vector<int>> st;
        sort(pairs.begin(), pairs.end(), [](vector<int>& a, vector<int>& b) {
            return a[1] < b[1];
        });
        
for (auto pair : pairs) { if (st.empty()) st.push(pair); else { auto t = st.top(); if (pair[0] > t[1]) st.push(pair); } } return st.size(); } };

我們可以對上面解法的空間進行優化,並不需要用棧來記錄最長鏈上的每一個鏈對。而是用一個變數end來記錄當前比較到的尾元素的值,初始化為最小值,然後遍歷的時候,如果當前鏈對的首元素大於end,那麼結果res自增1,end更新為當前鏈對的尾元素,參見程式碼如下:

解法二:

class Solution {
public:
    int findLongestChain(vector<vector<int>>& pairs) {
        int res = 0, end = INT_MIN;
        sort(pairs.begin(), pairs.end(), [](vector<int>& a, vector<int>& b) {
            return a[1] < b[1];
        });
        for (auto pair : pairs) {
            if (pair[0] > end) {
                ++res;
                end = pair[1];
            }
        }
        return res;
    }
};

這道題論壇上最火的解法是用DP來做的,但是博主認為Greedy能解的就沒有必要利用到DP,而且還不省空間,有點殺雞用牛刀的感覺。不過話說這道題鏈來鏈去,為啥會讓博主想到啥啥蜈蚣啊,什麼鬼。。。

類似題目:

參考資料: