Longest Increasing Subsequence
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ nums.length ≤ 12 - ◆
-1000 ≤ nums[i] ≤ 1000
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Recursive Without Memoization
BruteAt every index there are exactly two choices: leave the current number out of the subsequence, or fold it in as the new last element — but only when it's still increasing, meaning it's larger than whatever number was picked most recently. Tracking that "most recently picked" number as a second parameter alongside the current index turns the whole problem into a tree of skip/take decisions: try leaving the number out, try taking it (when allowed), and keep whichever path reaches the end of the array having picked more numbers. Nothing about a decision at one index is remembered when a different path reaches that same index with the same "last picked" value, so the same sub-problem gets solved over and over.
O(2^n)O(n)1class Solution {
2 private int[] nums;
3
4 public int lengthOfLIS(int[] nums) {
5 this.nums = nums;
6 return solve(0, -1);
7 }
8
9 private int solve(int i, int prev) {
10 if (i == nums.length) return 0;
11 int skip = solve(i + 1, prev);
12 int take = 0;
13 if (prev == -1 || nums[i] > nums[prev]) {
14 take = 1 + solve(i + 1, i);
15 }
16 return Math.max(skip, take);
17 }
18}Optimal — Bottom-Up 1D DP
OptimalLet dp[i] hold the length of the longest increasing subsequence that ends exactly at index i. On its own, every index is a subsequence of length 1, so every entry starts at 1. To grow dp[i] further, look back at every earlier index j: whenever nums[j] is smaller than nums[i], the run ending at j can be extended by nums[i], giving a candidate length of dp[j] + 1. Taking the best such candidate across all valid j — and defaulting to 1 when none qualify — fills in dp[i] using only entries that were already finalized earlier in the pass. The answer is whichever dp[i] ends up largest, since the longest increasing subsequence overall has to end somewhere.
O(n²)O(n)1class Solution {
2 public int lengthOfLIS(int[] nums) {
3 int n = nums.length;
4 int[] dp = new int[n];
5 Arrays.fill(dp, 1);
6 int best = 1;
7 for (int i = 1; i < n; i++) {
8 for (int j = 0; j < i; j++) {
9 if (nums[j] < nums[i]) {
10 dp[i] = Math.max(dp[i], dp[j] + 1);
11 }
12 }
13 best = Math.max(best, dp[i]);
14 }
15 return best;
16 }
17}