每天60秒读懂世界:6月10日外贸增长、卫星通信、学位改革与新能源车趋势解读
2026/6/12 1:16:00
nums中,找出一个连续的子数组。滑动窗口就像一个可以伸缩的“长方形框子”,我们在数组上维持这个框子:
right(右指针):负责探索新世界。它不断向右移动,把新数字拉进窗口。left(左指针):负责清理门户。一旦发现新拉进来的数字和窗口里的数字重复了,left就必须向右移动,直到把重复的那个旧数字踢出窗口。std::unordered_set在这道题中,我们需要极快地判断一个数字“在不在当前的窗口里”。C++ 的哈希集合std::unordered_set<int>是最佳选择。
| 操作 | 错误写法(类似 Map) | 正确集合语法 | 作用 |
|---|---|---|---|
| 检查是否存在 | if (seen[x])❌ | seen.count(x)✅ | 返回 1 代表存在,0 代表不存在 |
| 加入集合 | seen[x]++❌ | seen.insert(x)✅ | 将元素x放入登记表 |
| 移出集合 | 无 ❌ | seen.erase(x)✅ | 将元素x从登记表中删除 |
⚠️注意:
unordered_set是一个只记录“有没有”的集合,不支持[]下标操作和++、--运算。
while而不是if?在发现新数字重复时,我们必须使用while (seen.count(nums[right]))。
if,左指针left只会向右移动一步。如果重复的数字在窗口靠后的位置,移动一步并不能消除重复,此时强行加入新数字就会破坏“无重复”的规则。使用while可以让left一直向右退,直到窗口内彻底没有这个重复数字为止。当窗口缩小(left右移)时,必须同时更新三个状态:
current_sum-=nums[left];// 1. 从当前总和中扣除seen.erase(nums[left]);// 2. 从哈希表中注销left++;// 3. 左指针右移完整的标准解题逻辑如下,你可以以此作为最终编写代码的参考:
classSolution{public:intmaximumUniqueSubarray(vector<int>&nums){unordered_set<int>seen;// 登记表:记录当前窗口内的数字intcurrent_sum=0;// 记录当前窗口内数字的总和intmax_sum=0;// 记录历史最高得分intleft=0;// 左指针// 右指针遍历整个数组for(intright=0;right<nums.size();++right){// 1. 发现重复,左指针持续收缩窗口,直到重复数字被踢出while(seen.count(nums[right])){current_sum-=nums[left];seen.erase(nums[left]);left++;}// 2. 将新数字安全地加入窗口seen.insert(nums[right]);current_sum+=nums[right];// 3. 每次窗口稳定后,更新最大得分max_sum=max(max_sum,current_sum);}returnmax_sum;}};