300.最长递增子序列
我一开始的想法是第i个数时,往找所有比他小的数的nums[j],用数组记录dp[j],排序后取末尾然后从这其中选择一个最大的加1。
dp[i]的含义时以nums[i]为末尾结束的最长递增子序列。
后来发现可以优化成不用数组。直接每次取dp[j]时比较
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int m=1;
vector<int> dp(nums.size(),1);
for(int i=1;i<nums.size();i++){
for(int j=i;j>=0;j--){
if(nums[j]<nums[i]){
dp[i]=max(dp[i],dp[j]+1);
}
}
m=max(dp[i],m);
}
return m;
}
};
674. 最长连续递增序列
滑动窗口
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
int left=0,right=0;
int result=1;
for(int i=1;i<nums.size();i++){
if(nums[i]>nums[right]){
right++;
result=max(result,right-left+1);
}
else{
right=i;
left=i;
}
}
return result;
}
};
dp
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
vector<int> dp(nums.size(),1);
int result=1;
for(int i=1;i<nums.size();i++){
if(nums[i]>nums[i-1]){
dp[i]=dp[i-1]+1;
result=max(result,dp[i]);
}
}
return result;
}
};
718. 最长重复子数组
题目
这里一个很巧妙的地方是用一个二维数组来记录所有的情况
dp[i][j]表示以nums1的第i个元素结尾和nums2的第j个元素结尾的最长重复子数组。
if(nums1[i]==nums2[j]){
dp[i][j]=dp[i-1][j-1]+1;
//两个数组要同时回退
}
else{
dp[i][j]=0;//其实可以省略
//为什么不是dp[i-1][j]和dp[i][j-1]的最大值呢?
//因为它要求子数组必须是连续的,所以如果i处j处不相等还赋予它值的,在i+1和j+1处会取到中间有空袭的最长重复子数组
}
m=max(m,dp[i][j]);
上面这种写法就需要单独初始化第一行和第一列
int m=0;
for(int i=0;i<nums1.size();i++){
if(nums1[i]==nums2[0]){
dp[i][0]=1;
m=1;
}
}
for(int j=0;j<nums2.size();j++){
if(nums1[0]==nums2[j]){
dp[0][j]=1;
m=1;
}
}