Longest Increasing Sub-sequence
Given an unsorted array of integers, find the length of longest increasing sub-sequence.
Example
Given [10, 9, 2, 5, 3, 7, 101, 18]
,
The longest increasing sub-sequence is [2, 3, 7, 101]
, therefore the length is 4
. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in complexity.
Follow up
Improve it to O(n log n) time complexity?
Think #1
- Setup one dimensional array to memorize the longest sub-sequence on each element
- One pass on each element,
- But it need to go through the previous indexes to check any elements less than current element and compare the maximum by
max(current, prev +1)
Solution #1
/**
* @param nums: The integer array
* @return: The length of LIS (longest increasing subsequence)
*/
public int longestIncreasingSubsequence(int[] nums) {
if(nums == null || nums.length == 0)
return 0;
int[] memo = new int[nums.length];
int max = 0;
for(int i = 0; i < nums.length; i ++) {
memo[i] = 1;
for(int j = 0; j < i; j++) {
if(nums[j] < nums[i]) {
memo[i] = Math.max(memo[i], memo[j] + 1);
}
max = Math.max(memo[i], max);
}
}
return max;
}
Think #2
- Setup an array
table
with the length ofnums
- One pass on each element and initial max cursor is
0
intable
- Replace the element in
table
is just larger than current passing element - If current element is largest, increase the cursor in
table
- Finally, the the cursor + 1 is the max length.
Solution #2
/**
* @param nums: The integer array
* @return: The length of LIS (longest increasing subsequence)
*/
public int longestIncreasingSubsequence(int[] nums) {
if(nums == null || nums.length == 0)
return 0;
int[] memo = new int[nums.length];
int max = 0;
memo[0] = nums[0];
for(int i = 1; i < nums.length; i++) {
if(nums[i] < memo[0])
memo[0] = nums[i];
else if(memo[max] <= nums[i])
// equal or not depend on question requirement
memo[++max] = nums[i];
else{
int idx = findCeil(memo, max, nums[i]);
memo[idx] = nums[i];
}
}
return ++max;
}
/**
* @param arr: the memo array
* @param right index: current max in the memo array
* @param val: target value
* @return: where should val put in memo array
*/
private int findCeil(int[] arr, int r, int val){
int l = 0;
while(l + 1 < r) {
int m = l + ((r - l)>>1);
if(arr[m] < val)
l = m;
else
r = m;
}
return r;
}