Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18]
,
The longest increasing subsequence 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 O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
Credits:
Special thanks to @pbrother for adding this problem and creating all test cases.
class Solution {
public:
// There's a typical DP solution with O(N^2) Time and O(N) space
// DP[i] means the result ends at i
// So for dp[i], dp[i] is max(dp[j]+1), for all j < i and nums[j] < nums[i]
int lengthOfLIS(vector<int>& nums) {
const int size = nums.size();
if (size == 0) { return 0; }
vector<int> dp(size, 1);
int res = 1;
for (int i = 1; i < size; ++i) {
for (int j = 0; j < i; ++j) {
if (nums[j] < nums[i]) {
dp[i] = max(dp[i], dp[j]+1);
}
}
res = max (res, dp[i]);
}
return res;
}
};
第二种是复杂度O(nlogn)的二分查找方法。建立数组存放可能存在的升序子序列。从头遍历nums,试图把每一个num放到dp相应的位置里,最后返回dp存下的最长升序自序列的长度。代码如下:
public class Solution {
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
int size = 0;
for (int x: nums) {
int i = -1, j = size;
while (i + 1 < j) {
int mid = i + (j - i) / 2;
if (dp[mid] < x) {
i = mid;
} else {
j = mid;
}
}
if (i < 0) {
dp[0] = x;
} else {
dp[i + 1] = x;
}
if (i + 1 == size) {
dp[size] = x;
size ++;
}
}
return size;
}
}