标签:二分 nums int leetcode300 len 数组 序列 dp 贪心
链接:https://leetcode-cn.com/problems/longest-increasing-subsequence/
题目
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
用例
示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
示例 2:
输入:nums = [0,1,0,3,2,3]
输出:4
示例 3:
输入:nums = [7,7,7,7,7,7,7]
输出:1
提示:
1 <= nums.length <= 2500
-104 <= nums[i] <= 104
进阶:
你可以设计时间复杂度为 O(n2) 的解决方案吗?
你能将算法的时间复杂度降低到 O(n log(n)) 吗?
思路
方法一
动态规划 记录第一个位置到每一个位置最大距离 O(n^2)
注意*max_element(dp.begin(),dp.end());取数组最大值
转移方程dp[i]=max(dp[j]+1,dp[i]) ,nums[i]>nums[j],i>j
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
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);
}
}
}
return *max_element(dp.begin(),dp.end());
}
};
方法二
贪心
维护一个数组,记录在长度固定的情况下,结尾最小的那个元素的数值
对原序列进行遍历,将每位元素二分插入 cell 中。
如果 cell 中元素都比它小,将它插到最后
否则,用它覆盖掉比它大的元素中最小的那个。
思想就是让 cell 中存储比较小的元素。这样,cell 未必是真实的最长上升子序列,但长度是对的。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int len=1,n=nums.size();
vector<int>d(n+1,0);
d[len]=nums[0];
for(int i=1;i<n;++i){
if(nums[i]>d[len]){
d[++len]=nums[i];
}else{
int l=1,r=len,pos=0;//说明所有数都比nums[i]大,需要更新d数组
while(l<=r){
int mid=(l+r)>>1;
if(d[mid]<nums[i]){
pos =mid;
l=mid +1;
}else{
r=mid-1;
}
}
d[pos+1]=nums[i];
}
}
return len;
}
};
标签:二分,nums,int,leetcode300,len,数组,序列,dp,贪心 来源: https://www.cnblogs.com/kitamu/p/15428677.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。