灵神算法题单——不定长滑动窗口(求最长最大)

1208. 尽可能使字符串相等

简单的滑动窗口三部曲:移入窗口、是否移出、更新结果。

算差值这里采用abs()函数来实现

class Solution {
public:
    int equalSubstring(string s, string t, int maxCost) {
    int l=s.size();
    int ant=0,mi=INT_MIN;
    for(int i=0,j=0;i<l;i++)
    {
        ant+=abs(s[i]-t[i]);
        while(j<=i&&ant>maxCost)
        {
            ant-=abs(s[j]-t[j]);
            j++;
        }
        mi=max(mi,i-j+1);
    }
return mi;
    }
};

2779. 数组的最大美丽值

先排序然后进行区间合并,也可看出是一种滑动窗口

class Solution {
public:
    int maximumBeauty(vector<int>& nums, int k) {
        int ma=INT_MIN;int ant=0;
        sort(nums.begin(),nums.end());
        int l=nums.size();
        int r=nums[0]+k;
        for(int i=0,j=0;i<l;i++)
        {
                ant++;
            while(j<=i&&nums[i]-k>r)
            {
                j++;ant--;
                r=nums[j]+k;
            }
            ma=max(ma,i-j+1);
        }
        return ma;
    }
};

1658. 将 x 减到 0 的最小操作数

这道题可以理解为求窗口内值恰好为sum-x时窗口的最长值,当然经过转换变为未入窗口的最小值。

首先遍历一遍数组求出总和,算出差后面滑动窗口即可

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
     int sum=0;
     for(auto i:nums)sum+=i;
     if(x>sum)return -1;
     int cha=sum-x;int l=nums.size();
     int ant=0,mi=INT_MAX;
     for(int i=0,j=0;i<l;i++)
     {
      ant+=nums[i];
      while(j<=i&&ant>cha)
      {
        ant-=nums[j];
        j++;
      }
      if(cha==ant)mi=min(mi,l-i+j-1);
     }
     return mi==INT_MAX?-1:mi;
    }
};

1838. 最高频元素的频数

这个题也是与顺序无关所以我们先排序,假设窗口内都加到与nums[i]一样,如果k不够,则移动j

由于数值有点大,需要开long long  

class Solution {
public:
    int maxFrequency(vector<int>& nums, int k) {
     sort(nums.begin(),nums.end());
     long long ma=0;long long  ant=0;
     int l=nums.size();
     for(long long i=0,j=0;i<l;i++)
     {
        ant+=i==0?0:(i-j)*(nums[i]-nums[i-1]);
        while(j<=i&&ant>k)
        {
            ant-=nums[i]-nums[j];
            j++;
        }
        ma=max(ma,i-j+1);
     }
     return ma;
    }
};

2516. 每种字符至少取 K 个

跟上一题类似,转换为求窗口内每种字符最多取总数-k个,最后转换一下即可。

class Solution {
public:
    int takeCharacters(string s, int k) {
        int l =s.size();
     int a[5]={0};
      for(auto i:s)a[i-'a']++;
      for(int i=0;i<3;i++)
      {a[i]-=k;if(a[i]<0)return -1;}

      int ma=0,ant=0;
      for(int i=0,j=0;i<l;i++)
      {
         a[s[i]-'a']--;
         while(j<=i&&a[s[i]-'a']<0)
         {
            a[s[j]-'a']++;
            j++;
         }
         ma=max(ma,i-j+1);
      }

      return l-ma;
    }
};

2271. 毯子覆盖的最多白色砖块数

贪心加滑动窗口加排序

class Solution {
public:
    int maximumWhiteTiles(vector<vector<int>>& tiles, int carpetLen) {
        sort(tiles.begin(),tiles.end());
        int n=tiles.size();
        int ant=0,ma=0;
        for(int i=0,j=0;i<n;i++)
        {
            ant+=tiles[i][1]-tiles[i][0]+1;
            while(j<=i&&tiles[i][1]-tiles[j][1]>=carpetLen)
            {
                ant-=tiles[j][1]-tiles[j][0]+1;
                j++;
            }
          ma=max(ma,ant-max(0,tiles[i][1]-carpetLen+1-tiles[j][0]));
        }
          return ma;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值