每日算法刷题Day11 5.20:leetcode不定长滑动窗口求最长/最大6道题,结束不定长滑动窗口求最长/最大,用时1h20min

6. 1695.删除子数组的最大得分(中等)

1695. 删除子数组的最大得分 - 力扣(LeetCode)

思想

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

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

2.题意转换:窗口内不含相同元素,哈希表维护即可

代码

c++:

复制代码
class Solution {
public:
    int maximumUniqueSubarray(vector<int>& nums) {
        int n = nums.size();
        int res = 0;
        map<int, int> cnt;
        int left = 0;
        int sum = 0;
        for (int right = 0; right < n; ++right) {
            sum += nums[right];
            ++cnt[nums[right]];
            while (cnt[nums[right]] > 1) {
                --cnt[nums[left]];
                sum -= nums[left];
                ++left;
            }
            res = max(res, sum);
        }
        return res;
    }
};
7. 2958.最多K个重复元素的最长子数组(中等)

2958. 最多 K 个重复元素的最长子数组 - 力扣(LeetCode)

思想

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

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

2.题意转换:所有元素的频率都 小于等于 k即为窗口条件

代码

c++:

复制代码
class Solution {
public:
    int maxSubarrayLength(vector<int>& nums, int k) {
        int n = nums.size();
        int res = 0;
        map<int, int> cnt;
        int left = 0;
        for (int right = 0; right < n; ++right) {
            ++cnt[nums[right]];
            while (cnt[nums[right]] > k) {
                --cnt[nums[left]];
                ++left;
            }
            res = max(res, right - left + 1);
        }
        return res;
    }
};
8. 2024.考试的最大困扰度(中等,可一起考虑优化)

2024. 考试的最大困扰度 - 力扣(LeetCode)

思想

1.方法是 最大化连续相同 结果的题数,请你返回在不超过 k 次操作的情况下,最大 连续 'T' 或者 'F' 的数目。

2.我的思想,F和T分开来求,两个最大值再取最大值

3.学习优化思想:

窗口内有4种情况:

  • T和F数量都不超过k,满足要求
  • T数量超过k,F数量不超过k,把F变成T,满足要求
  • F数量超过k,T数量不超过k,把T变成F,满足要求
  • T和F数量都超过k,不满足要求,更新窗口左端点
代码

c++:

复制代码
class Solution {
public:
    int solve(string answerKey, int k,char c){
        int n=answerKey.size();
        int left=0;
        int sum=0; 
        int res=0;
        for(int right=0;right<n;++right){
            if(answerKey[right]==c)   ++sum;
            while(sum>k){
                if(answerKey[left]==c)    --sum;
                ++left;
            }
            res=max(res,right-left+1);
        }
        return res;
    }
    int maxConsecutiveAnswers(string answerKey, int k) {
        // F->T
        int resT=solve(answerKey,k,'F');
        // T->F
        int resF=solve(answerKey,k,'T');
        int res=max(resT,resF);
        return res;
    }
};

优化:

复制代码
class Solution {
public:
    int maxConsecutiveAnswers(string answerKey, int k) {
        int n = answerKey.size();
        int left = 0;
        int sumT = 0, sumF = 0;
        int res = 0;
        for (int right = 0; right < n; ++right) {
            if (answerKey[right] == 'T')
                ++sumT;
            else
                ++sumF;
            while (sumT > k && sumF > k) {
                if (answerKey[left] == 'T')
                    --sumT;
                else
                    --sumF;
                ++left;
            }
            res = max(res, right - left + 1);
        }
        return res;
    }
};
9. 1004.最大连续1的个数III(中等)

1004. 最大连续1的个数 III - 力扣(LeetCode)

思想

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

2.题目理解:0的数量不超过k

代码

c++:

复制代码
class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int n = nums.size();
        int res = 0;
        int sum0 = 0;
        int left = 0;
        for (int right = 0; right < n; ++right) {
            if (nums[right] == 0)
                ++sum0;
            while (sum0 > k) {
                if (nums[left] == 0)
                    --sum0;
                ++left;
            }
            res = max(res, right - left + 1);
        }
        return res;
    }
};
10. 1658.将x减到0的最小操作数(中等,逆向思维)

1658. 将 x 减到 0 的最小操作数 - 力扣(LeetCode)

思想

1.给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1

2.逆向思维转换:求和为totalSum-x的最长窗口大小

3.逆向思维转换后k=totalSum-x,要判断k为负的特殊情况

4.res初始值设置为INT_MIN,先判断-1情况

代码

c++:

复制代码
class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int n = nums.size();
        int res = INT_MIN;
        long long totalSum = 0, sum = 0;
        for (const int val : nums)
            totalSum += (long long)val;
        long long k = totalSum - x;
        if (k < 0)
            return -1;
        int left = 0;
        for (int right = 0; right < n; ++right) {
            sum += (long long)nums[right];
            while (sum > k) {
                sum -= (long long)nums[left];
                ++left;
            }
            if (sum == k) {
                res = max(res, right - left + 1);
            }
        }
        if (res == INT_MIN)
            return -1;
        return n - res;
    }
};
相关推荐
TL滕1 天前
从0开始学算法——第十六天(双指针算法)
数据结构·笔记·学习·算法
蒲小英1 天前
算法-贪心算法
算法·贪心算法
mit6.8241 天前
链式投票|流向贪心
算法
君义_noip1 天前
洛谷 P4777 【模板】扩展中国剩余定理(EXCRT)
算法·数论·信息学奥赛·csp-s
天赐学c语言1 天前
12.14 - 搜索旋转排序数组 && 判断两个结构体是否相等
数据结构·c++·算法·leecode
1024肥宅1 天前
JavaScript 性能与优化:数据结构和算法
前端·数据结构·算法
kaikaile19951 天前
MATLAB 灰度图像的二维傅里叶变换
算法·计算机视觉·matlab
仰泳的熊猫1 天前
1112 Stucked Keyboard
数据结构·c++·算法·pat考试
roman_日积跬步-终至千里1 天前
【计算机算法与设计(14)】例题五:最小生成树:Prim算法详细解释:π的含义、更新逻辑和选点原因
算法
让学习成为一种生活方式1 天前
压缩文件夹下下所有文件成压缩包tar.gz--随笔016
算法