最直接去重取数量的方式是用std::set构造并调用size(),但大数据量时推荐std::unordered_set(平均o(n));若内存受限可排序后遍历计数;处理vector须用begin()/end()而非sizeof。

用 std::set 去重后取 size() 最直接
对普通数组(或 std::vector),最常用也最不容易出错的方式是把元素插入 std::set,它自动去重,再调用 size():
int arr[] = {1, 2, 2, 3, 4, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
std::set<int> s(arr, arr + n);
std::cout
<p>注意:这要求元素类型支持比较操作(如 <code>int</code>、<code>string</code> 默认支持)。如果自定义类型没重载 <code>,编译会报错 <code>invalid operands to binary expression</code>。</code></p>
<p>常见坑:</p>
<ul>
<li>
<code>std::set</code> 插入是 <code>O(n log n)</code>,大数据量时比 <code>std::unordered_set</code> 慢</li>
<li>别误写成 <code>std::set<int> s = {arr};</int></code> —— 这只会插入一个指针值,不是展开数组</li>
</ul>
<h3>用 <code>std::unordered_set</code> 提升性能</h3>
<p>如果只关心个数、不关心顺序,且元素类型支持 <code>hash</code>(如 <code>int</code>、<code>std::string</code>),<code>std::unordered_set</code> 平均 <code>O(n)</code>,更高效:</p>
<pre class="brush:php;toolbar:false;">
std::unordered_set<int> us(arr, arr + n);
std::cout
<p>但要注意:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>自定义类型必须提供 <code>std::hash</code> 特化,否则编译失败:<code>use of deleted function 'std::hash<mytype>::hash()'</mytype></code>
</li>
<li>重复插入同一值不会报错,也不会影响结果,这是预期行为</li>
<li>内存占用略高,但对多数场景可忽略</li>
</ul>
<h3>原地排序 + 单次遍历(适合只读、无额外空间需求)</h3>
<p>如果不能用额外容器,且允许修改原数组,先排序再线性扫描是经典解法:</p>
<pre class="brush:php;toolbar:false;">
std::sort(arr, arr + n);
int count = n > 0 ? 1 : 0;
for (int i = 1; i
<p>适用场景:</p>
- 嵌入式环境或内存极度受限
- 数组本身已部分有序,
std::sort实际开销小 - 元素类型不可哈希也不可比较(比如只有
==可用)——这时只能靠两两比较,但复杂度升到O(n²),慎用
处理 std::vector 或迭代器范围时别硬算长度
如果数据来自 std::vector<int> v</int>,别再用 sizeof(v)/sizeof(v[0]) —— 这永远返回 sizeof(std::vector),不是元素个数:
std::vector<int> v = {1, 2, 2, 3};
std::set<int> s(v.begin(), v.end()); // 正确
// std::set<int> s(v.data(), v.data() + v.size()); // 也可,但多此一举
</int></int></int>
关键点:
- 统一用
v.begin()/v.end()或v.data()/v.data() + v.size() - 如果传入空容器,
std::set构造正常,size()返回 0,无需额外判空 - C++20 起可用
std::ranges::unique配合std::distance,但兼容性和可读性不如前几种
std::unordered_set;真要抠内存或不能改数据,才考虑排序+遍历。别为了“看起来更底层”而绕开标准容器——它们已经足够快,也足够可靠。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










