使用vector时反复触发std::out_of_range异常的技术求助
问题分析与解决
异常原因
你遇到的std::out_of_range异常核心是越界访问vector元素,同时循环逻辑存在明显错误:
- 循环条件
k != nums.size() + 1完全不合理,当k走到nums.size()时,nums.at(k)和nums.at(k+1)都会访问超出vector合法范围的位置(vector有效索引是0到nums.size()-1)。 - 即使
k没到末尾,当k = nums.size()-1时,k+1 = nums.size(),此时nums.at(k+1)直接触发越界异常。 - 删除元素后仍自增
k:erase会让vector长度减小,后续元素自动前移,这时候自增k会跳过原本要检查的元素,甚至继续触发越界。
修正后的基础版代码
void removeDuplicates(vector<int>& nums) { int k = 0; // 循环条件保证k+1始终是合法索引 while (k < nums.size() - 1) { if (nums[k] == nums[k + 1]) { // 删除当前重复元素,后续元素前移,k不递增,继续检查当前位置 nums.erase(nums.begin() + k); } else { // 元素不重复,移动到下一个位置 ++k; } } }
关键修改说明
- 循环条件改为
k < nums.size() - 1:从根源上保证每次访问nums[k+1]都在合法范围内,避免越界。 - 删除元素后不递增
k:erase操作会把后续元素往前移一位,原来的k+1位置元素现在到了k位置,需要继续检查这个新元素是否和下一个重复。 - 去掉冗余迭代器变量:直接用
nums.begin() + k作为erase的参数,简化代码。
更高效的双指针写法
基础版因为多次调用erase(每次erase是O(n)复杂度),整体时间复杂度为O(n²)。如果处理大数据量,推荐用双指针法将时间复杂度优化到O(n):
void removeDuplicates(vector<int>& nums) { if (nums.empty()) return; int slow = 0; for (int fast = 1; fast < nums.size(); ++fast) { // 找到不同元素时,慢指针移动并赋值 if (nums[fast] != nums[slow]) { nums[++slow] = nums[fast]; } } // 最后删除慢指针之后的所有重复元素 nums.erase(nums.begin() + slow + 1, nums.end()); }
内容的提问来源于stack exchange,提问作者Gleb Bespalov
相关产品推荐
相关产品推荐

