Longest Increasing Subsequence
JavaView on GFG
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
- 1tails = [].
- 2For each num: binary search for the position in tails where tails[pos] >= num.
- 3If pos == tails.Length, append num (extend LIS). Else replace tails[pos] = num.
- 4Return tails.Length.
Example Walkthrough
Input: arr = [10,9,2,5,3,7,101,18]
- 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.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?