当前位置: 首页 > news >正文

每日算法刷题计划Day12 5.21:leetcode不定长滑动窗口求最短/最长3道题,,用时1h40min(有点长了)

求最短/最小

一般题目都有「至少」的要求。
窗口成立的条件,right右移增强条件,然后while循环left右移最终破坏条件

模版套路

在while循环内更新答案

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int n=nums.size();long long sum=0;int res=INT_MAX;int left=0;for(int right=0;right<n;++right){// 1.入窗口sum+=nums[right];// 2.满足条件while(sum>=target){// 2.1 更新答案res=min(res,right-left+1);// 2.2 出窗口sum-=nums[left];++left;}}// 无答案if(res==INT_MAX)    return 0;return res;}
};
套路
题目描述

1.找出该数组中满足其总和大于等于 target (窗口条件)的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度**。如果不存在符合条件的子数组,返回 0 。
2.如果 s 的某个子字符串中 1 的个数恰好等于 k(窗口条件) ,则称这个子字符串是一个 美丽子字符串 。令 len 等于 最短 美丽子字符串的长度。返回长度等于 len 且字典序 最小 的美丽子字符串。如果 s 中不含美丽子字符串,则返回一个  字符串。(两重最小,长度最小+字典序最小)
3.假如在该字符串中,这四个字符都恰好出现 n/4 次(题目条件,而不是窗口条件),那么它就是一个「平衡字符串」。给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。请返回待替换子串的最小可能长度。(题意转换,窗口内字符是可以替换的,即窗口内字符是任意分配的(不用具体在意是什么),能够让窗口外字符数量增加,但不会减少,所以一个窗口满足的条件就是窗口外4种字符的数量都小于等于n/4)

学习经验

1.与求最长/最大不同,最长/最大右移right会导致窗口不满足条件,所以while循环内是不满足条件就右移left直到满足条件,while循环结束窗口满足条件,更新答案。(while外更新答案)
而求最短/最小,右移right肯定更加满足条件,所以while循环内满足条件就先更新答案,然后右移left,直到不满足条件,然后right接着右移。(while内更新答案)
另一种思想是while中先假设右移left,若满足条件就进入while,然后真正右移left,while循环结束窗口肯定也满足条件,再判断满足条件(刚开始不一定满足)然后更新答案(while外更新答案)

1. 209.长度最小的子数组(中等,学习)

209. 长度最小的子数组 - 力扣(LeetCode)

思想

1.找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度**。如果不存在符合条件的子数组,返回 0
2.我的想法比较复杂,想跟求最长/最大套路一样,窗口不满足条件更新窗口,但是这题右移right会一直满足条件,所以想到左移left,但是得先找到第一个满足条件的窗口。所以先右移right找到第一个满足条件的区间[0,right),然后依次左移left,不满足条件就while右移right,使得区间[left+1,right)为窗口,但是因为right是开区间,会遇到无法再右移的情况,需要一个tag变量进行判断,并在res更新前判断tag退出for循环,调试了一会。
3.学习:
依旧是枚举右端点移动,简单直接
(1)在while循环结束后更新答案

  • 1.right入窗口
  • 2.假设left左移,如果sum-nums[left]>=target,那么就while左移left
  • 3.满足条件(判断一开始不满足条件的情况,能左移说明左移完肯定满足条件)则更新res
    (2)在while循环内更新答案(学习)
  • 1.right入窗口
  • 2.满足要求进入while循环,先更新答案,后左移left
代码

c++:
1.我的

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int n = nums.size();long long sum = 0;int right = 0;while (right < n && sum < target) {sum += nums[right];++right;}if (sum < target)return 0;int res = right;bool tag = false;// 区间:[left+1,right)for (int left = 0; left < n; ++left) {sum -= nums[left];while (sum < target) {if (right == n) {tag = true;break;}sum += nums[right];++right;}if (tag)break;res = min(res, right - left - 1);}return res;}
};

2.在while循环外更新答案

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int n = nums.size();long long sum = 0;int left = 0;int res = INT_MAX;for (int right = 0; right < n; ++right) {sum += nums[right];while (sum - nums[left] >= target) {sum -= nums[left];++left;}if (sum >= target)res = min(res, right - left + 1);}if (res == INT_MAX)return 0;return res;}
};

3.在while循环内更新答案

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int n=nums.size();long long sum=0;int res=INT_MAX;int left=0;for(int right=0;right<n;++right){sum+=nums[right];while(sum>=target){res=min(res,right-left+1);sum-=nums[left];++left;}}if(res==INT_MAX)    return 0;return res;}
};
2. 2904.最短且字典序最小的美丽子字符串(中等)

2904. 最短且字典序最小的美丽子字符串 - 力扣(LeetCode)

思想

1.如果 s 的某个子字符串中 1 的个数恰好等于 k(窗口条件) ,则称这个子字符串是一个 美丽子字符串 。令 len 等于 最短 美丽子字符串的长度。返回长度等于 len 且字典序 最小 的美丽子字符串。如果 s 中不含美丽子字符串,则返回一个  字符串。
2.这题要求答案字符串长度最短且字典序最小,两重最小
3.字符串初始设置最大值string strmax(n+1,'z')
4.字符串重要的substr(pos,len)函数

代码

c++:

class Solution {
public:string shortestBeautifulSubstring(string s, int k) {int n = s.size();long long sum1 = 0;string strmax(n + 1, 'z'); // 初值最大值,等价于INT_MAXstring res = strmax;int left = 0;for (int right = 0; right < n; ++right) {if (s[right] == '1')++sum1;while (sum1 == k) {string t = s.substr(left, right - left + 1);if (t.size() < res.size()) {res = t;} else if (t.size() == res.size()) {res = min(res, t);}if (s[left] == '1')--sum1;++left;}}if (res == strmax)return "";return res;}
};
3. 1234.替换子串得到平衡字符串(中等,学习思想)

1234. 替换子串得到平衡字符串 - 力扣(LeetCode)

思想

1.假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。请返回待替换子串的最小可能长度
2.题意转换,窗口内字符是可以替换的,即窗口内字符是任意分配的(不用具体在意是什么),能够让窗口外字符数量增加,但不会减少,所以一个窗口满足的条件就是窗口外4种字符的数量都小于等于n/4, 从而窗口内的字符能分配使总字符都为n/4
所以需要维护每种字符窗口外的数量,利用map

代码

c++:

class Solution {
public:int balancedString(string s) {int n = s.size();int avg = n / 4;unordered_map<char, int> cnt;for (char c : s)++cnt[c];if (cnt['Q'] == avg && cnt['W'] == avg && cnt['E'] == avg &&cnt['R'] == avg)return 0;int res = INT_MAX;int left = 0;for (int right = 0; right < n; ++right) {// 入窗口相当于窗口外字符数量减少--cnt[s[right]];while (cnt['Q'] <= avg && cnt['W'] <= avg && cnt['E'] <= avg &&cnt['R'] <= avg) {res = min(res, right - left + 1);// 出窗口相当于窗口外字符数量增加++cnt[s[left++]];}}return res;}
};

相关文章:

  • SQLMesh 宏操作符详解:@IF 的条件逻辑与高级应用
  • 使用 Matter.js 创建封闭箱体与里面的小球
  • Python学习Day1:安装
  • 数独求解器3.0 增加latex格式读取
  • 通过TDE透明加密实现SQL Server数据库免改造加密
  • SQL 数值计算全解析:ABS、CEIL、FLOOR与ROUND函数深度精讲
  • 红杉资本2025 AI 峰会之Cybersecurity
  • 一文理解TCP与UDP
  • [CSS3]百分比布局
  • 第十三届蓝桥杯国赛PythonA题解
  • epoll_wait未触发的小Bug
  • Axure应用交互设计:动态面板嵌套实现超强体验感菜单表头
  • DL00987-基于深度学习YOLOv11的红外鸟类目标检测含完整数据集
  • Java 项目管理工具:Maven 与 Gradle 的深度对比与选择
  • Spring Boot 登录实现:JWT 与 Session 全面对比与实战讲解
  • Qt初识.
  • qt---命名规范
  • 目标检测 RT-DETR(2023)详细解读
  • 嵌入式开发学习日志(linux系统编程--文件读写函数(2))Day24
  • wd软件安装
  • 积分商城网站开发/域名收录