You need to enable JavaScript to run this app. C++ STL unordered_set实现无序数组缺失元素查询的逻辑与效率疑问
优惠活动
大模型
产品
解决方案
定价
更多

C++ STL unordered_set实现无序数组缺失元素查询的逻辑与效率疑问

1. 查找缺失元素的逻辑

unordered_set是STL提供的基于哈希表实现的无序集合,核心特性是:存储的元素无重复,平均情况下插入、查找元素的时间复杂度都是O(1)。
这段代码的执行逻辑分为两步:

  • 第一步遍历输入数组的所有元素,全部插入unordered_set中,自动完成去重
  • 第二步就是你贴的核心循环:逐个遍历[low, high]区间内的所有整数x:
    调用s.find(x)查找x是否在集合中,如果返回迭代器等于s.end(),说明x没有出现在原数组中,属于缺失元素,直接打印输出。

以你给出的示例为例:原数组元素为[1,3,5,4,2,8,7],插入到集合后包含的元素就是18,遍历110时,9、10查找失败,所以最终输出结果为9 10。

2. 效率分析与更优方案

当前方案的效率

  • 平均时间复杂度:O(n + L),其中n是原数组长度,L = high - low + 1是区间长度。插入n个元素平均耗时O(n),遍历区间的L次查找每次平均O(1)。
  • 缺点:哈希表有额外的内存开销,存在哈希碰撞的最坏情况,最坏情况查找复杂度退化到O(n),整体耗时会变成O(n*L);如果区间长度L特别大(比如到1e9级别),遍历整个区间完全不可行。

更高效的实现方案

根据场景不同有两种更优选择:

场景A:区间长度L不大(比如小于1e6)

用布尔数组替代unordered_set,完全规避哈希开销,运行速度更快,内存更紧凑:

void printMissing(int arr[], int n, int low,int high) {
    int range = high - low + 1;
    vector<bool> exist(range, false);
    for (int i = 0; i < n; i++) {
        // 只标记在区间内的元素
        if (arr[i] >= low && arr[i] <= high) {
            exist[arr[i] - low] = true;
        }
    }
    for (int i = 0; i < range; i++) {
        if (!exist[i]) cout << low + i << " ";
    }
}

场景B:区间长度L远大于数组长度n

对原数组排序后直接遍历找空缺,时间复杂度仅和数组长度相关,不受区间大小影响:

void printMissing(int arr[], int n, int low,int high) {
    sort(arr, arr + n);
    int cur = low;
    for (int i = 0; i < n && cur <= high; i++) {
        // 跳过小于当前待检查值的重复/无效元素
        if (arr[i] < cur) continue;
        // 中间有空缺,全部是缺失元素
        if (arr[i] > cur) {
            while (cur < arr[i] && cur <= high) {
                cout << cur << " ";
                cur++;
            }
        }
        cur = arr[i] + 1;
    }
    // 输出数组最大值之后的剩余缺失元素
    while (cur <= high) {
        cout << cur << " ";
        cur++;
    }
}

这个方案的时间复杂度是O(n log n),当区间长度L远大于n*log n的时候,效率远高于前两种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 16:42:02