2026.6.9
2026/6/11 23:58:05 网站建设 项目流程

📚 LeetCode 1695. 删除子数组的最大得分 —— 学习笔记


📌 一、 题目核心解析

  • 题目要求:从一个正整数数组nums中,找出一个连续的子数组。
  • 限定条件
  1. 子数组内不能有重复的数字(所有元素独一无二)。
  2. 该子数组的元素之和(得分)要最大
  • 核心思路:求连续片段的问题,通常优先考虑使用滑动窗口(Sliding Window)算法,避免暴力双重循环导致的超时。

🛠️ 二、 核心算法:滑动窗口(双指针)

滑动窗口就像一个可以伸缩的“长方形框子”,我们在数组上维持这个框子:

  1. right(右指针):负责探索新世界。它不断向右移动,把新数字拉进窗口。
  2. left(左指针):负责清理门户。一旦发现新拉进来的数字和窗口里的数字重复了,left就必须向右移动,直到把重复的那个旧数字踢出窗口。

🧰 三、 C++ 关键工具箱: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是一个只记录“有没有”的集合,不支持[]下标操作和++--运算。


🚨 四、 避坑指南(易错点盘点)

1. 为什么必须用while而不是if

在发现新数字重复时,我们必须使用while (seen.count(nums[right]))

  • 原因:如果使用if,左指针left只会向右移动一步。如果重复的数字在窗口靠后的位置,移动一步并不能消除重复,此时强行加入新数字就会破坏“无重复”的规则。使用while可以让left一直向右退,直到窗口内彻底没有这个重复数字为止。

2. 移除元素时的“三步走”

当窗口缩小(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;}};

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询