/**
* 自己的解法,从后往前dp,dp中每个元素代表从当前开头的LIS
* 时间复杂度O(n^2),不是最优
* Runtime: 61 ms, faster than 32.89%
* Memory Usage: 38.3 MB, less than 83.56%
*/
class Solution {
public int lengthOfLIS(int[] nums) {
int longest = 1;
int[] dp = new int[nums.length];
for (int i = nums.length - 1; i >= 0; i--) {
dp[i] = 1;
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] < nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
longest = Math.max(longest, dp[i]);
}
return longest;
}
}
/**
* genius做法
* tails[i]表示到目前为止,i-1长度的LIS,最小的结尾值
* tails显然是一个递增数组,所以可以在tails中二分查找找到第一个大于nums[i]的元素,用nums[i]替代它
* 时间复杂度O(nlogn)
* Runtime: 2 ms, faster than 98.88%
* Memory Usage: 38.3 MB, less than 92.02%
*/
class Solution {
public int lengthOfLIS(int[] nums) {
int[] tails = new int[nums.length];
tails[0] = nums[0];
int longest = 1;
for (int i = 1; i < nums.length; i++) {
if (nums[i] > tails[longest - 1]) { // nums[i]比前面的数字都大,longest变长,tails数组多一个值
tails[longest++] = nums[i];
} else { // 二分查找找到tails数组中,比nums[i]大(or等于nums[i])的第一个,更新它的值为nums[i]
int left = 0, right = longest - 1;
while (left < right) {
int mid = (left + right) / 2;
if (nums[i] > tails[mid]) {
left = mid + 1;
} else {
right = mid;
}
}
tails[left] = nums[i];
}
}
return longest;
}
}