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].

Solution:

dp

class Solution {
    public int findLongestChain(int[][] pairs) {
        Arrays.sort(pairs, (a, b) -> { return Integer.compare(a[0], b[0]); });
        int n = pairs.length;
        int max = 1;
        int[] dp = new int[n];
        for (int i = 0; i < n; i ++) {
            dp[i] = 1;
            for (int j = 0; j < i; j ++) {
                if (pairs[j][1] < pairs[i][0]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            max = Math.max(max, dp[i]);
        }
        return max;
    }
}

greedy

The optimal solution: greedy solution: beat 100%
Sort the pairs by pair[1] (tail).
Try add each pair from left to right.
Why this works?
Consider pairA and pairB, where pairA appears before pairB in the sorted pairs.
That implies that pairA[1] < pairB[1], but there is no constraint on pairA[0] and pairB[0].
Now, the greedy part is: I claim that it's always better to try to add pairA to the chain first.
Let's prove that:


  1. When pairA[1] < pairB[0], it's obvious that we should append pairA first.
    
  2. When pairA[1] >= pairB[0], we have to choose carefully, because that means:
         either we only append pairA to the chain,
         or we only append pairB to the chain.
     Append either pairA or pairB will increment the length of the chain by 1.
     However: (note: cur is the tail of the chain)
         appending pairA will have cur = pairA[1],
         appending pairB will have cur = pairB[1].
         And pairA[1] < pairB[1]
     Apparently, we shall append pairA first because that way we expose a smaller tail which has a better opportunity to append more future pairs.


public class Solution {
    public int findLongestChain(int[][] pairs) {
        if(pairs == null || pairs.length ==0 ) return 0;
        Arrays.sort(pairs, (a, b) -> (a[1] - b[1]));
        int res=1, end = pairs[0][1];
        for(int i =1; i<pairs.length; i++) {
            if(pairs[i][0]>end){
                res++;
                end = pairs[i][1];
            }
        }
        return res;
    }
}