给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
动态规划:
dp[i]
: nums
数组中前i
个元素的最长上升子数组的长度
对于0 <= j < i
包含数组nums[i] "向前看"
:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
int res = 1;
if(n == 0) {
return 0;
}
vector<int> dp(n,1);
for(int i = 0; i < n; i++) {
for(int j = 0; j < i; j++) {
if(nums[j] < nums[i])
dp[i] = max(dp[i], dp[j] + 1);
res = max(dp[i],res);
}
}
return res;
}
基于二分查找的动态规划:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
//存放纸牌堆最上面的元素(最小的)
vector<int> top(n,0);
int piles = 0; //纸牌堆数
for(int i = 0; i < n; i++) {
int poker = nums[i];//当前要处理的牌
int left = 0, right = piles;
//搜索左侧边界的二分查找
while(left < right) {
int mid = (left + right) / 2;
if(top[mid] > poker)
right = mid;
else if(top[mid] < poker)
left = mid + 1;
else
right = mid;
}
//没有合适的 新建一个牌堆
if(left == piles)
piles++;
top[left] = poker;
}
return piles;
}
同类型题目:
递增的三元子序列
思考O(N)的解法 (维护两个变量 贪心+双指针)
打家劫舍
思考如何将空间复杂度降到O(1)?
使用滚动数组,在每个时刻只需要存储前两间房屋的最高总金额.
int first = nums[0], second = max(nums[0], nums[1]);
for (int i = 2; i < n; i++) {
int tmp = second;
second = max(first + nums[i], second);
first = tmp;
}
爬楼梯
思考空间复杂度为O(1)的情况?