You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classSolution {
public:intlengthOfLIS(vector<int>& nums) {
if (nums.empty()) return0;
vector<int> ends{nums[0]};
for (auto a : nums) {
if (a < ends[0]) ends[0] = a;
elseif (a > ends.back()) ends.push_back(a);
else {
int left = 0, right = ends.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (ends[mid] < a) left = mid + 1;
else right = mid;
}
ends[right] = a;
}
}
return ends.size();
}
};
class Solution {
public int lengthOfLIS(int[] nums) {
int n = nums.length;
int[] dp = new int[n];
dp[0] = nums[0];
int len = 1;
for (int i = 1; i < nums.length; i++) {
int pos = binarySearch(dp,len - 1, nums[i]);
if (pos == len && dp[pos - 1] < nums[i]) {
dp[len++] = nums[i];
} else {
dp[pos] = nums[i];
}
}
return len;
}
private int binarySearch(int[] dp, int len, int val) {
int left = 0;
int right = len;
int mid = 0;
while (left <= right) {
mid = left + (right - left) / 2;
if (dp[mid] == val) {
return mid;
} else {
if (dp[mid] < val) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return left > mid ? right + 1 : left;
}
}
用了贪心的思想,维护一个最小数组队列。
时隔一年,重新写了一下做法:
class Solution {
public int lengthOfLIS(int[] nums) {
int len = 0, n = nums.length;
int[] dp = new int[n + 1];
dp[0] = -10001;
for (int num : nums) {
if (num > dp[len]) {
dp[++len] = num;
}
for (int i = len; i > 0; --i) {
if (num > dp[i - 1]) {
dp[i] = Math.min(dp[i], num);
}
}
}
return len;
}
}
进一步优化可以用二分。
class Solution {
public int lengthOfLIS(int[] nums) {
int len = -1, ans = 0;
int[] dp = new int[nums.length];
for (int num : nums) {
int lo = 0, hi = len + 1;
while (lo < hi) {
int mid = (lo + hi) >> 1;
if (dp[mid] >= num) {
hi = mid;
} else {
lo = mid + 1;
}
}
dp[lo] = num;
len = lo > len ? lo : len;
ans = Math.max(len + 1, ans);
}
return ans;
}
}
Given an unsorted array of integers, find the length of longest increasing subsequence.
Example:
Note:
Follow up: Could you improve it to O(n log n) time complexity?
可以和#23对比。
经典的线性DP问题。设置一个长为同题目数组长度一样的dp一维数组,dp[i]代表位置i之前的最长公共递增公共子序列。dp[i] = max(dp[i], dp[i - j] + 1),其中nums[j] <= nums[i] && j < i。
如果要把时间复杂度优化为O(n logn),显然需要用到二分查找法,而二分查找法是针对有序数组的,所以我们需要对新数组(存放结果的)进行二分查找。
上述做法实际上类似维护了一个单调栈(不保证顺序),也扯上了些贪心的思想,每次按最小增长序列来算。用Java的话可以用一个数组来显示:
用了贪心的思想,维护一个最小数组队列。
时隔一年,重新写了一下做法:
进一步优化可以用二分。
类似题目:
参考资料:
The text was updated successfully, but these errors were encountered: