2026/4/18 12:38:31
网站建设
项目流程
万网没备案怎么做网站,河南省住建局官方网站,丹阳市住房和城乡建设局网站,石家庄公司网络推广1 题目
3090. 每个字符最多出现两次的最长子字符串
给你一个字符串 s #xff0c;请找出满足每个字符最多出现两次的最长子字符串#xff0c;并返回该子字符串的 最大 长度。
示例 1#xff1a;
输入#xff1a; s bcbbbcba
输出#xff1a; 4
解释请找出满足每个字符最多出现两次的最长子字符串并返回该子字符串的最大长度。示例 1输入s bcbbbcba输出4解释以下子字符串长度为 4并且每个字符最多出现两次bcbbbcba。示例 2输入s aaaa输出2解释以下子字符串长度为 2并且每个字符最多出现两次aaaa。提示2 s.length 100s仅由小写英文字母组成。2 代码实现联想和第三题的框架完全一致先贴一个leetcode3的解法。3. 无重复字符的最长子串class Solution { public: int lengthOfLongestSubstring(string s) { unordered_mapchar , int window ; int left 0 , right 0 ; int res 0 ; while (right s.size()){ char c s[right] ; right; window[c]; while (window[c] 1 ){ char d s[left]; left ; window[d] --; } res max (res,right - left); } return res; } };本题做法class Solution { public: int maximumLengthSubstring(string s) { unordered_mapchar , int window; int left 0 ; int right 0; int res 0 ; while (right s.size()){ char c s [right ]; right ; window[c]; while(window[c] 2){ char d s[left]; left ; window[d]--; } res max(res , right - left ); } return res; } };总结收缩左边界的核心目的让滑动窗口[left, right)重新回到无重复字符的状态这是我们计算最长无重复子串长度的前提。收缩左边界的逻辑从最左侧开始依次移出字符直到当前重复的字符c的计数满足条件此时窗口内不再有重复字符。整个滑动窗口的策略右指针扩展窗口找新字符左指针收缩窗口去重过程中持续记录窗口的最大长度。3 题目1493. 删掉一个元素以后全为 1 的最长子数组给你一个二进制数组nums你需要从中删掉一个元素。请你在删掉元素的结果数组中返回最长的且只包含 1 的非空子数组的长度。如果不存在这样的子数组请返回 0 。提示 1输入nums [1,1,0,1]输出3解释删掉位置 2 的数后[1,1,1] 包含 3 个 1 。示例 2输入nums [0,1,1,1,0,1,1,0,1]输出5解释删掉位置 4 的数字后[0,1,1,1,1,1,0,1] 的最长全 1 子数组为 [1,1,1,1,1] 。示例 3输入nums [1,1,1]输出2解释你必须要删除一个元素。提示1 nums.length 105nums[i]要么是0要么是1。4 代码实现思考删掉一个0元素以后最长的全1数组长度那么如果没有删除就是一个数组最长里面有且仅有一个0元素其余都是1的元素。思路维护一个滑动窗口只含有一个0这个窗口最长的长度。根本不需要和题目的操作一样顺着来这个先删除的操作最后这个窗口的长度减去一就是答案了自己写的错误百出的代码class Solution { public: int longestSubarray(vectorint nums) { unordered_map int , int window; int left 0 ; int right 0 ; int res 0 ; while (right nums.size()){ right ; if (nums[right] 1 ){ window[1]; }else{ window[0]; } while(window[0] 1){ left ; if(nums[left] 1 ){ window[1]--; }else{ window[0]--; } } res max(res , window[1] - 1); } return res ; } };首先明确你的核心需求你想要实现的功能是给定一个由 0 和 1 组成的数组删除最多一个0也可以不删后找到最长的连续 1 的子数组长度。代码中存在的关键问题数组越界问题right执行后直接访问nums[right]当right达到nums.size()时会访问到数组的越界位置导致程序崩溃。收缩窗口的逻辑错误while(window[0] 1)的条件错误应该是当窗口内的 0 的数量超过 1 时才收缩窗口因为题目允许删除最多一个 0。左指针移动后的计数错误收缩窗口时先执行left再访问nums[left]会漏掉对nums[left]初始位置的字符计数修改导致window的计数不准确。结果计算错误res max(res, window[1] - 1)会错误地将 1 的计数减 1正确的应该是直接取窗口内的有效长度或window[1]根据逻辑调整。修复后的完整代码#include vector #include unordered_map #include algorithm using namespace std; class Solution { public: int longestSubarray(vectorint nums) { unordered_mapint, int window; // 键0或1值对应数字在窗口中的出现次数 int left 0, right 0; int res 0; int max_ones 0; // 记录窗口内1的最大数量 int zero_count 0; // 窗口内0的数量也可以用window[0]单独变量更直观 while (right nums.size()) { int num nums[right]; right; // 右指针扩展窗口 // 更新窗口内的计数 if (num 1) { window[1]; max_ones max(max_ones, window[1]); // 记录1的最大数量 } else { window[0]; zero_count; } // 当窗口内0的数量超过1时收缩左边界因为最多只能删一个0 while (zero_count 1) { int left_num nums[left]; left; // 左指针收缩窗口 // 更新计数 if (left_num 1) { window[1]--; } else { window[0]--; zero_count--; // 关键0的数量减1退出循环的关键 } } // 计算当前窗口的有效长度窗口长度right-left- 1因为必须删除一个元素即使是0 // 题目要求是“删除一个元素后”的长度所以不管有没有0都要减1 res max(res, right - left - 1); } return res; } };代码关键部分解释解决数组越界先取nums[right]的值再执行right避免访问越界的位置。收缩窗口的条件当zero_count 1时窗口内有超过 1 个 0收缩左边界直到 0 的数量≤1符合最多删一个 0 的要求。计数更新逻辑收缩左边界时先取nums[left]的值再执行left确保计数修改的是当前左指针指向的元素。结果计算right - left - 1是删除一个元素后的窗口长度题目要求必须删除一个元素即使数组全是 1也要删一个比如[1,1,1]的结果是 2。如果题目允许不删除元素即最多删一个则可以调整为max(res, zero_count 0 ? right - left - 1 : right - left)。测试用例我们用几个例子验证代码的执行效果输入nums [1,1,0,1]过程窗口会包含[1,1,0,1]0 的数量 1有效长度 4-13结果为 3。输入nums [0,1,1,1,0,1,1,0,1]有效长度为 5比如窗口[1,1,1,0,1,1]长度 6-15结果为 5。输入nums [1,1,1]有效长度 3-12结果为 2。自行修正后代码实现class Solution { public: int longestSubarray(vectorint nums) { unordered_map int , int window; int left 0 ; int right 0 ; int res 0 ; while (right nums.size()){ int a nums[right]; right ; if (a 1 ){ window[1]; }else{ window[0]; } while(window[0] 1){ int b nums[left]; left ; if(b 1 ){ window[1]--; }else{ window[0]--; } } res max(res , right - left - 1); } return res ; } };测试通过小结好像感受到一些思路了的确这种题目有固定的模板也就是通用的解法按照这个边总结边练习的方式刷题效果好了很多加油(ง •_•)ง