nums
LIS LIS[i] = longest increasing subsequence that starts at nums[i] · filled right to left
public int lengthOfLIS(int[] nums) { int n = nums.length; int[] LIS = new int[n]; Arrays.fill(LIS, 1); for (int i = n - 1; i >= 0; i--) { for (int j = i + 1; j < n; j++) { if (nums[i] < nums[j]) { LIS[i] = Math.max(LIS[i], 1 + LIS[j]); } } } return Arrays.stream(LIS).max().getAsInt();}
- i
- —
- j
- —
- nums[i], nums[j]
- —
- LIS[i]
- —
Why it works
- Brute force tries every subsequence: 2ⁿ of them, each checked in O(n).
- Fix the first pick: an increasing subsequence starting at
ieither stops there (length 1) or continues at some laterjwithnums[j] > nums[i]. SoLIS[i] = 1 + max(LIS[j])over thosej. The arc fromLIS[j]intoLIS[i]is that continuation. - Two nested loops: each
iscans everyjto its right, and those cells are already final because the outer loop runs right to left. About n²/2 comparisons: O(n²) time, O(n) space. - Pitfall: the answer is
max(LIS), notLIS[0]: the best subsequence need not start at index 0. And "increasing" is strict, so[7,7,7]gives 1. - Follow-up, O(n log n): keep
tails[k], the smallest possible last value of an increasing subsequence of length k + 1, and binary-search where each number goes (patience sorting).