代码随想录算法训练营第36期DAY56

DAY56

套磁很顺利,发现又有书读了!

300最长递增子序列

  1. 朴素法,这个好想,但是不对,比如

0 1 0 3 2 3

我的算法会找出0 1 3作为答案,而不是0 1 2 3

可以看出,后面的状态依赖于前面的状态:选了前面的3,就不会选出后面的2 3;

没选前面的3,就能够选出后面的2 3.

错误代码:

  1. class Solution {
  2. public:
  3.     int lengthOfLIS(vector<int>& nums) {
  4.         int len=1;
  5.         for(int i=0;i<nums.size();i++){
  6.             int ilen=1;
  7.             int left=nums[i];
  8.             for(int j=i+1;j<nums.size();j++){
  9.                 if(left<nums[j]){
  10.                     ilen++;
  11.                     left=nums[j];
  12.                 }
  13.             }
  14.             len=max(len,ilen);
  15.         }
  16.         return len;
  17.     }
  18. };

  1. 动态规划,第一次接触,积攒经验。

Dp[i]的定义:dp[i]表示i之前包括i的以nums[i]为结尾的最长递增子序列的长度。

“尾部元素”很重要。

状态转移方程:好理解,遍历的思想

认真手写推导了,掌握了。

Code:

记得最后返回的是res就行,而不是dp的末位。

  1. class Solution {
  2. public:
  3.     int lengthOfLIS(vector<int>& nums) {
  4.         vector<intdp(nums.size(),1);
  5.         int res=1;
  6.         for(int i=1;i<nums.size();i++){
  7.             for(int j=0;j<i;j++){
  8.                 if(nums[i]>nums[j]) dp[i]=max(dp[i],dp[j]+1);
  9.             }
  10.             if(dp[i]>res) res=dp[i];
  11.         }
  12.         return res;
  13.     }
  14. };

674最长连续递增序列

复习。滑动窗口法。

精心总结滑动窗口代码模板, 直接搞定80道Leetcode算法题_哔哩哔哩_bilibili

朴素法:

  1. class Solution {
  2. public:
  3.     int findLengthOfLCIS(vector<int>& nums) {
  4.         //朴素
  5.         int res=1;
  6.         for(int i=0;i<nums.size()-1;i++){
  7.             for(int j=i;j<nums.size()-1;j++){
  8.                 if(nums[j]>=nums[j+1]) break;
  9.                 res=max(res,j+2-i);
  10.             }
  11.         }
  12.         return res;
  13.     }
  14. };

双指针:

  1. class Solution {
  2. public:
  3.     int findLengthOfLCIS(vector<int>& nums) {
  4.         //双指针
  5.         int res=1;
  6.         for(int l=0;l<nums.size();l++){
  7.             int r=l+1;
  8.             while(r<nums.size()&&nums[r]>nums[r-1]) r++;
  9.             res=max(res,r-l);
  10.         }
  11.         return res;
  12.     }
  13. };

滑动窗口复习:

精心总结滑动窗口代码模板, 直接搞定80道Leetcode算法题_哔哩哔哩_bilibili

练习:

209长度最小的子数组,中等

注意模版中,对与最长问题,要在外部while去更新bestres;

而在最短问题,需要在内部while去更新bestres;

  1. class Solution {
  2. public:
  3.     int minSubArrayLen(int target, vector<int>& nums) {
  4.         int l=0,r=0,bestres=0;
  5.         int cursum=0;
  6.         while(r<nums.size()){
  7.             cursum+=nums[r];
  8.             while(r<nums.size()&&cursum>=target){
  9.                 //这一句if也很重要
  10.                 if(r-l+1<bestres||bestres==0) bestres=r-l+1;
  11.                 cursum-=nums[l];
  12.                 l++;
  13.             }
  14.             r++;
  15.         }
  16.         return bestres;
  17.     }
  18. };

ACWING799最长连续不重复子序列

799最长连续不重复子序列_哔哩哔哩_bilibili

讲得很好,主要是要手写模拟一遍。

CODE:

  1. #include<iostream>
  2. using namespace std;
  3. const int N=100010;
  4. int n;
  5. int a[N],b[N];
  6. int main(){
  7.     cin>>n;
  8.     int res=0;
  9.     for(int i=0;i<n;i++) cin>>a[i];
  10.     // i denotes begin, j denotes end
  11.     for(int i=0,j=0;j<n;j++){
  12.         b[a[j]]++;
  13.         while(j>i&&b[a[j]]>1) b[a[i++]]--;
  14.         res=max(res,j-i+1);
  15.     }
  16.     cout<<res<<endl;
  17.     return 0;
  18. }

674最长连续递增序列

  1. 朴素 简单啦
  1. class Solution {
  2. public:
  3.     int findLengthOfLCIS(vector<int>& nums) {
  4.         int res=1;
  5.         for(int i=0;i<nums.size();i++){
  6.             int ilen=1;
  7.             for(int j=i+1;j<nums.size();j++){
  8.                 if(nums[j-1]<nums[j]) ilen++;
  9.                 else break;
  10.             }
  11.             res=max(res,ilen);
  12.         }
  13.         return res;
  14.     }
  15. };

  1. 双指针
  1. class Solution {
  2. public:
  3.     int findLengthOfLCIS(vector<int>& nums) {
  4.         int res=1;
  5.         for(int l=0;l<nums.size()-1;l++){
  6.             int llen=1;
  7.             int r=l+1;
  8.             while(r<nums.size()&&nums[r-1]<nums[r]) llen++,r++;
  9.             res=max(res,llen);
  10.         }
  11.         return res;
  12.     }
  13. };

  1. 动态规划

自己想出来了,很好。

  1. class Solution {
  2. public:
  3.     int findLengthOfLCIS(vector<int>& nums) {
  4.         int res=1;
  5.         vector<intdp(nums.size(),1);
  6.         for(int i=1;i<nums.size();i++){
  7.             if(nums[i-1]<nums[i]) dp[i]=dp[i-1]+1;
  8.             res=max(res,dp[i]);
  9.         }
  10.         return res;
  11.     }
  12. };

718最长重复子数组

  1. 很容易想到双指针,但是难点在于,怎么处理定位函数中,有多个定位函数结果,比如:

[0,1,3,2,5,8,9,7]

[0,5,4,2,6,2,3,4]

还是用动态规划吧。

  1. 动态规划,没接触过。

子数组就是连续子序列,没问题。

要想到:用二维数组记录两个字符串的所有比较情况。

学完了,在纸上手动推导一下DP数组:已完成。

一定要记得size()+1 初始化vector时候。

For()循环里也是<=size了,不然比较不完。

  1. class Solution {
  2. public:
  3.     int findLength(vector<int>& nums1, vector<int>& nums2) {
  4.         int res = 0;
  5.         // 一定要记得size()+1
  6.         vector<vector<int>> dp(nums1.size() + 1,
  7.                                vector<int>(nums2.size() + 10));
  8.         for (int i = 1; i <= nums1.size(); i++) {
  9.             for (int j = 1; j <= nums2.size(); j++) {
  10.                 if (nums1[i - 1] == nums2[j - 1])
  11.                     dp[i][j] = dp[i - 1][j - 1] + 1;
  12.                 res = max(res, dp[i][j]);
  13.             }
  14.         }
  15.         return res;
  16.     }
  17. };

  • 51
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值