不定长滑动窗口-基础篇(2)

1.题目删除子数组的最大得分

给你一个正整数数组 nums ,请你从中删除一个含有 若干不同元素 的子数组**。** 删除子数组的 得分 就是子数组各元素之

返回 只删除一个 子数组可获得的 最大得分

如果数组 b 是数组 a 的一个连续子序列,即如果它等于 a[l],a[l+1],...,a[r] ,那么它就是 a 的一个子数组。

复制代码
输入:nums = [4,2,4,5,6]
输出:17
解释:最优子数组是 [2,4,5,6]

这道题翻译成人话就是:找没有重复元素的子数组,统计最大和,子数组包含隐藏条件------连续,不是子序列。

cpp 复制代码
class Solution {
public:
    int maximumUniqueSubarray(vector<int>& nums) {
        unordered_set<int> st;
        int ans=0;
        int sum=0;
        int left=0;
        for(int x : nums){
            while(st.contains(x)){
                st.erase(nums[left]);
                sum-=nums[left];
                left++;
            }
            st.insert(x);
            sum+=x;
            ans=max(ans,sum);
        }
        return ans;
    }
};

这道题是跟力扣的第三题.无重复字符的最长子串是一样的,额外维护窗口中的元素和即可。

2.题目最多 K 个重复元素的最长子数组

给你一个整数数组 nums 和一个整数 k

一个元素 x 在数组中的 频率 指的是它在数组中的出现次数。

如果一个数组中所有元素的频率都 小于等于 k ,那么我们称这个数组是 数组。

请你返回 nums最长好 子数组的长度。

子数组 指的是一个数组中一段连续非空的元素序列。

复制代码
输入:nums = [1,2,3,1,2,3,1,2], k = 2
输出:6
解释:最长好子数组是 [1,2,3,1,2,3] ,值 1 ,2 和 3 在子数组中的频率都没有超过 k = 2 。[2,3,1,2,3,1] 和 [3,1,2,3,1,2] 也是好子数组。
最长好子数组的长度为 6 。
cpp 复制代码
class Solution {
public:
    int maxSubarrayLength(vector<int>& nums, int k) {
        int ans=0;
        int left=0;
        unordered_map<int,int> cnt;
        for(int right=0;right<nums.size();right++){
            cnt[nums[right]]++;
            while(cnt[nums[right]]>k){
                cnt[nums[left]]--;
                left++;
            }
            ans=max(ans,right-left+1);
        }
        return ans;
    }
};

对于本题,新加入元素 x=nums[right] 后,如果 x 的出现次数超过 k,则不断右移左指针 left,直到窗口内的 x 的出现次数等于 k 为止,然后用窗口大小 right−left+1 更新答案的最大值。

3.题目考试的最大困扰度

一位老师正在出一场由 n 道判断题构成的考试,每道题的答案为 true (用 'T' 表示)或者 false (用 'F' 表示)。老师想增加学生对自己做出答案的不确定性,方法是 最大化连续相同 结果的题数。(也就是连续出现 true 或者连续出现 false)。

给你一个字符串 answerKey ,其中 answerKey[i] 是第 i 个问题的正确结果。除此以外,还给你一个整数 k ,表示你能进行以下操作的最多次数:

  • 每次操作中,将问题的正确答案改为 'T' 或者 'F' (也就是将 answerKey[i] 改为 'T' 或者 'F' )。

请你返回在不超过 k 次操作的情况下,最大 连续 'T' 或者 'F' 的数目。

复制代码
输入:answerKey = "TTFF", k = 2
输出:4
解释:我们可以将两个 'F' 都变为 'T' ,得到 answerKey = "TTTT" 。
总共有四个连续的 'T' 。
cpp 复制代码
class Solution {
public:
    int maxConsecutiveAnswers(string answerKey, int k) {
        int t=0;
        int f=0;
        int left=0;
        int ans=0;
        for(int right=0;right<answerKey.size();right++){
            if(answerKey[right]=='T') t++;
            else f++;
            while(min(t,f)>k){
                if(answerKey[left]=='T') t--;
                else f--;
                left++;
            }
            ans=max(ans,right-left+1);
        }
        return ans;
    }
};

这道题目的意思就是:求 answerKey 的一个最长子串,包含至多 k 个 T 或者至多 k 个 F。

由于子串越长,越无法满足要求,有单调性,可以用滑动窗口解决。

1.遍历 answerKey,枚举子串右端点 right,同时维护最小左端点 left 以及子串中的字符个数 cnt。

2.把 answerKey[right] 的出现次数加一。

3.如果 T 和 F 的出现次数都超过 k,那么必须不断移动左端点 left,同时减少 answerKey[left] 的出现次数,直到 T 和 F 的出现次数至少有一个 ≤k。

4.循环结束后,说明子串右端点在 right 时,对应的最小左端点为 left,用子串长度 right−left+1 更新答案的最大值。

5.遍历 answerKey 结束后,返回答案。

我这个题解写的稍微清楚一点,其实也可以使用位运算来写,这样可以更快一点。

4.题目最大连续1的个数 III

给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k0 ,则返回执行操作后 数组中连续 1 的最大个数

复制代码
输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
cpp 复制代码
class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int ans=0;
        int left=0;
        int cnt=0;
        for(int right=0;right<nums.size();right++){
            if(nums[right]==0) cnt++;
            while(cnt>k){
                if(nums[left]==0) cnt--;
                left++;
            }
            ans=max(ans,right-left+1);
        }
        return ans;
    }
};

cnt0 += 1 - nums[right]和cnt0 -= 1 - nums[left]

就相当于

if (nums[right] == 0) cnt0++;

if (nums[left] == 0) cnt0--;

这里是我之前写的代码,但是不方便理解,题解这样写就可以更好理解一些。

统计窗口内 0 的个数 cnt0​,则问题转化成在 cnt0​≤k 的前提下,窗口大小的最大值。

相关推荐
memmolo2 小时前
【3D测量中的术语:系统误差、随机误差、精密度、准确度】
算法·计算机视觉·3d
霑潇雨2 小时前
题解 | 分析每个商品在不同时间段的销售情况
数据库·sql·算法·笔试
金枪不摆鳍2 小时前
算法-动态规划
算法·动态规划
季明洵2 小时前
Java中哈希
java·算法·哈希
jaysee-sjc2 小时前
【练习十】Java 面向对象实战:智能家居控制系统
java·开发语言·算法·智能家居
cici158742 小时前
基于MATLAB实现eFAST全局敏感性分析
算法·matlab
gihigo19982 小时前
MATLAB实现K-SVD算法
数据结构·算法·matlab
vegetablesssss2 小时前
=和{}赋值区别
c++
dyyx1112 小时前
C++编译期数据结构
开发语言·c++·算法