DDSA Solutions

Longest Increasing Subsequence

Advertisement

Intuition

Two approaches: O(n²) DP where dp[i]=LIS ending at index i, or O(n log n) using patience sorting with a "tails" array. In the patience approach, tails[i] = smallest tail element of all increasing subsequences of length i+1.

Algorithm

  1. 1tails = [].
  2. 2For each num: binary search for the position in tails where tails[pos] >= num.
  3. 3If pos == tails.Length, append num (extend LIS). Else replace tails[pos] = num.
  4. 4Return tails.Length.

Example Walkthrough

Input: arr = [10,9,2,5,3,7,101,18]

  1. 1.10: [10]. 9: [9]. 2: [2]. 5: [2,5]. 3: [2,3]. 7: [2,3,7]. 101: [2,3,7,101]. 18: [2,3,7,18].
  2. 2.Length=4.

Output: 4

Common Pitfalls

  • The tails array does not represent the actual LIS — only its length is meaningful. Reconstruct using parent pointers from the O(n²) approach if needed.
Longest Increasing Subsequence.java
Java
// Approach: DP with binary search. Maintain a 'tails' array; binary search position for each element.
// Time: O(n log n) Space: O(n)
class Solution {
    static int lis(int arr[]) {
        int n = arr.length;
        if (n == 0)
            return 0; // Although constraint says size >= 1, good to handle empty case.

        int[] dp = new int[n];
        Arrays.fill(dp, 1); // Initialize dp array with 1s

        for (int i = 1; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (arr[j] < arr[i])
                    dp[i] = Math.max(dp[i], dp[j] + 1);
            }
        }

        int maxLen = 0;
        for (int len : dp)
            maxLen = Math.max(maxLen, len);

        return maxLen;
    }
}
Advertisement
Was this solution helpful?