c++中如何删除数组中的重复元素_c++数组去重实现

发布时间 - 2026-01-22 00:00:00    点击率:
首选 std::unordered_set 辅助去重以获得无重复副本,时间复杂度低且代码简洁;原地去重则用双指针法,O(n) 时间、O(1) 空间,需手动 resize。

std::setstd::unordered_set 辅助去重(适合原始数组不可变)

如果只是需要一份无重复的副本,且不关心原数组顺序是否保留,最稳妥的做法是借助标准容器自动去重。注意:std::set 会排序,std::unordered_set 保持插入顺序但需类型支持哈希。

  • int 数组,std::unordered_set 是首选:插入快、查重快、不改变逻辑顺序
  • 若原数组很大,反复调用 insert() 后再转回 vector,比手写双指针更易读、不易出错
  • 不能直接用于 C 风格数组(如 int arr[10]),必须先知道长度,或改用 std::vector
std::vector nums = {1, 2, 2, 3, 3, 4};
std::unordered_set seen;
std::vector unique;
for (int x : nums) {
    if (seen.insert(x).second) { // insert 返回 pair,second 为 true 表示新插入
        unique.push_back(x);
    }
}

原地去重:用双指针法处理

std::vector

这是最常用也最高效的原地去重方式,时间复杂度 O(n),空间 O(1),但要求元素可比较(如 ==),且只保留首次出现的元素。

  • 适用于已排序数组时效果最佳;未排序时也能用,但结果顺序不变,重复项被“挤掉”,末尾留垃圾值
  • 返回的是新逻辑长度,必须手动调用 resize() 才真正缩短容器
  • 别直接对裸数组(如 int arr[10])用双指针——没 size 信息,容易越界
std::vector v = {1, 2, 2, 3, 2, 4};
if (v.empty()) return;
size_t i = 0;
for (size_t j = 1; j < v.size(); ++j) {
    if (v[j] != v[i]) {
        v[++i] = v[j];
    }
}
v.resize(i + 1); // 关键:不 resize 就只是前 i+1 个有效

std::unique + erase 组合(仅适用于已排序数组)

std::unique 不是真的删除元素,它把重复项移到末尾并返回新尾迭代器。必须配合 erase 才算完成去重,而且只对相邻重复有效 —— 换句话说,数组必须先排序。

  • 误用场景:对未排序数组直接调 unique,只会删掉“连着出现”的重复,比如 {1,2,1} 变成 {1,2,1}(没变),因为两个 1 不相邻
  • 排序成本不可忽略:O(n log n),比双指针 O(n) 慢,除非你本来就要排序
  • std::vector 安全;对裸数组要用 std::unique(arr, arr + n),小心传错长度
std::vector v = {3, 1, 2, 1, 3, 2};
std::sort(v.begin(), v.end()); // 必须先排
auto last = std::unique(v.begin(), v.end());
v.erase(last, v.end());

处理 C 风格数组时的常见陷阱

很多人卡在“怎么对 int arr[10] 去重”,根本问题是:C 数组没有长度元信息,函数无法知道边界,传参必须显式带长度,且无法安全缩容。

  • 不能用 sizeof(arr)/sizeof(*arr) 在函数内求长度 —— 数组退化为指针后该表达式失效
  • 所谓“删除”只能是:把唯一元素前移,返回新有效长度,调用方负责用该长度访问
  • 如果真要缩容,必须换用 std::vector 或动态分配新内存 + memcpy,别试图 realloc 栈数组
// 正确传参方式
int removeDuplicates(int arr[], int n) {
    if (n == 0) return 0;
    int i = 0;
    for (int j = 1; j < n; ++j) {
        if (arr[j] != arr[i]) {
            arr[++i] = arr[j];
        }
    }
    return i + 1; // 新长度
}
// 调用方需记录返回值:int new_len = removeDuplicates(arr, 10);
裸数组去重没有银弹,关键在分清“要不要改原数组”“数组是否已排序”“能不能换容器”。用错 std::unique 或忽略 resize 是高频失误点。


#   # ai  # c++  # red  # c++数组  # int  # 指针  # 必须先  # 适用于  # 的是  # 这是  # 首次  # 很多人  # 只会  # 要用  # 问题是  # 不能用 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何实现API速率限制?(Rate Limiting教程)  轻松掌握MySQL函数中的last_insert_id()  零服务器AI建站解决方案:快速部署与云端平台低成本实践  如何用y主机助手快速搭建网站?  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  如何在橙子建站上传落地页?操作指南详解  EditPlus中的正则表达式 实战(4)  Laravel Livewire是什么_使用Laravel Livewire构建动态前端界面  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  Laravel怎么判断请求类型_Laravel Request isMethod用法  php json中文编码为null的解决办法  如何快速生成专业多端适配建站电话?  html5如何实现懒加载图片_ intersectionobserver api用法【教程】  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  Laravel如何实现模型的全局作用域?(Global Scope示例)  如何用美橙互联一键搭建多站合一网站?  油猴 教程,油猴搜脚本为什么会网页无法显示?  SQL查询语句优化的实用方法总结  品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?  如何用IIS7快速搭建并优化网站站点?  Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧  如何用狗爹虚拟主机快速搭建网站?  Laravel如何实现密码重置功能_Laravel密码找回与重置流程  深入理解Android中的xmlns:tools属性  如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】  如何在阿里云部署织梦网站?  iOS中将个别页面强制横屏其他页面竖屏  Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明  Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理  JS弹性运动实现方法分析  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  Internet Explorer官网直接进入 IE浏览器在线体验版网址  Laravel事件监听器怎么写_Laravel Event和Listener使用教程  猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】  Laravel如何使用Blade组件和插槽?(Component代码示例)  Laravel用户密码怎么加密_Laravel Hash门面使用教程  Java垃圾回收器的方法和原理总结  Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】  Laravel Asset编译怎么配置_Laravel Vite前端构建工具使用  Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】  使用C语言编写圣诞表白程序  谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复  图册素材网站设计制作软件,图册的导出方式有几种?  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  Laravel DB事务怎么使用_Laravel数据库事务回滚操作  如何在浏览器中启用Flash_2025年继续使用Flash Player的方法【过时】  Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能  微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】