You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

保留元素顺序的vector去重函数存在逻辑错误,求分析与实现思路

现有函数的逻辑错误

你的代码存在3个核心问题,导致仅相邻重复场景能生效:

  • 内层循环遍历逻辑错误:你的需求是保留元素第一次出现的顺序,也就是后续出现的、已经在前面出现过的元素要全部删除。但你内层循环固定从下标1开始遍历,当外层循环i走到靠后的下标时,不会对比i位置的元素是否已经在0~i-1区间出现过,反而会直接把i位置的元素当成要保留的基准,去删除后续的重复项,这就会导致前面已经出现过的元素在后面再次出现时被保留,比如你示例输出里重复的1就是这个原因导致的。
  • 删除元素后未处理下标偏移:调用erase删除x位置的元素后,原本x+1位置的元素会自动挪到x位置,此时你的代码直接执行x++会直接跳过这个新移动到x位置的元素,导致漏检部分重复项。
  • 外层循环边界动态变化但未适配:erase会缩小vector的长度,你外层循环的终止条件inputVector.size() - 1是动态变化的,极端场景下会出现下标越界的隐患。
手动实现的底层思路

我们的目标是:仅保留每个元素第一次出现的位置,后续重复元素全部删除,这里提供两种常用实现思路:

方案1:原地修改(O(n²)时间,O(1)额外空间)

适合内存紧张的场景,不需要额外申请存储结构,逻辑如下:

  1. 维护一个valid_idx变量表示当前已去重的有效区域的最后下标,初始值为0,0~valid_idx区间的元素都是已经完成去重、无重复的元素。
  2. 从下标1开始遍历整个vector的每个元素:
    • 检查当前元素是否在0~valid_idx区间内出现过
    • 如果没有出现过,就把valid_idx加1,将当前元素赋值到valid_idx的位置
    • 如果已经出现过,直接跳过当前元素
  3. 遍历完成后,将vector从valid_idx + 1到末尾的所有元素全部删除即可。

对应代码实现:

void vectorDeduplicator(std::vector<std::string>& inputVector){
    // 空vector直接返回
    if(inputVector.empty()) return;
    int valid_idx = 0;
    // 从第二个元素开始遍历
    for(int i = 1; i < inputVector.size(); i++){
        bool is_duplicate = false;
        // 检查当前元素是否在已去重区间出现过
        for(int j = 0; j <= valid_idx; j++){
            if(inputVector[i] == inputVector[j]){
                is_duplicate = true;
                break;
            }
        }
        if(!is_duplicate){
            valid_idx++;
            inputVector[valid_idx] = inputVector[i];
        }
    }
    // 截断后面的无效元素
    inputVector.erase(inputVector.begin() + valid_idx + 1, inputVector.end());
}

方案2:空间换时间(O(n)时间,O(k)额外空间,k为去重后元素数量)

适合对性能要求高的场景,用额外的存储结构记录已经出现过的元素,避免内层循环比对:

  1. 维护一个valid_idx变量表示当前已去重的有效区域的最后下标,初始值为0,同时用一个哈希集合记录已经出现过的元素。
  2. 遍历整个vector的每个元素:
    • 如果当前元素不在哈希集合中,就将它加入集合,赋值到valid_idx位置,然后valid_idx加1
    • 如果已经在集合中,直接跳过
  3. 遍历完成后,将vector从valid_idx到末尾的所有元素全部删除即可。

对应代码实现:

#include <unordered_set>
void vectorDeduplicator(std::vector<std::string>& inputVector){
    std::unordered_set<std::string> seen;
    int valid_idx = 0;
    for(int i = 0; i < inputVector.size(); i++){
        if(seen.find(inputVector[i]) == seen.end()){
            seen.insert(inputVector[i]);
            inputVector[valid_idx] = inputVector[i];
            valid_idx++;
        }
    }
    inputVector.erase(inputVector.begin() + valid_idx, inputVector.end());
}

两种方案都可以正确处理你给出的测试用例,输入1 1 2 2 4 4 3 3 1 1 3 3 3 2 2时,输出为[1,2,4,3],符合保留首次出现顺序去重的要求。

内容的提问来源于stack exchange,提问作者ool123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 22:27:00