set的初认识

在 C++ 中,set 是 有序、不重复 的关联容器(底层通常用红黑树实现),核心特性是 自动去重 + 自动排序,非常适合解决 “统计不同元素个数”“快速查找元素” 等场景。

1. 头文件与定义

使用 set 必须包含头文件 <set>,且需指定元素类型(如 intstring 等):

#include <set>
using namespace std; // 简化写法,否则需写 std::set

// 定义一个存储整数的 set(默认升序排序)
set<int> s;
2. 核心操作
操作代码示例功能说明时间复杂度
插入元素s.insert(5);插入元素,重复元素会自动忽略O(log n)
批量插入(数组)set<int> s(a, a+n);直接用数组区间 [a, a+n) 初始化 set,自动去重O(n log n)
获取元素个数s.size();返回 set 中不同元素的个数(题目核心需求)O(1)
清空容器s.clear();删除所有元素O(n)
判断是否为空s.empty();为空返回 true,否则返回 falseO(1)
查找元素s.find(3);查找元素 3,找到返回迭代器,否则返回 s.end()O(log n)

二、结合题目场景的实战用法

之前的题目核心是 “统计数组中不同元素的个数”,用 set 有两种常见实现方式,本质都是利用其 “自动去重” 特性:

方式 1:循环插入(适合动态添加元素)
int get_unique_count(int a[], int n) {
    set<int> s;
    for (int i = 0; i < n; i++) {
        s.insert(a[i]); // 重复元素会被自动过滤
    }
    return s.size(); // 直接返回不同元素个数
}
方式 2:区间初始化(代码更简洁)

set 支持用迭代器区间直接初始化,数组名本质是指针(可当作迭代器),因此可以一行完成数组元素的去重:

int get_unique_count(int a[], int n) {
    set<int> s(a, a + n); // 直接将数组 [a, a+n) 插入 set,自动去重
    return s.size();
}

这两种方式结果完全一致,方式 2 更简洁,推荐使用。

三、set 的进阶用法(拓展认知)

1. 遍历 set(查看排序后的元素)

set 是有序的(默认升序),可以通过迭代器遍历所有元素:

set<int> s = {2, 1, 3, 1, 5}; // 初始化时自动去重+排序为 [1,2,3,5]
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
    cout << *it << " "; // 输出:1 2 3 5
}
// C++11 及以上可简化为范围 for 循环
for (int x : s) {
    cout << x << " "; // 同样输出:1 2 3 5
}
2. 自定义排序(降序或自定义规则)

默认 set 是升序,若需降序,可在定义时指定排序规则:

// 降序排列的 set
set<int, greater<int>> s = {2, 1, 3, 1, 5};
for (int x : s) {
    cout << x << " "; // 输出:5 3 2 1
}
3. 删除元素

set<int> s = {1,2,3,4,5};
s.erase(3); // 删除元素 3(按值删除)
s.erase(s.begin()); // 删除第一个元素(按迭代器删除)
4. 查找元素是否存在
set<int> s = {1,2,3,4,5};
if (s.find(3) != s.end()) {
    cout << "元素 3 存在";
} else {
    cout << "元素 3 不存在";
}

四、set 的优缺点(对比辅助数组法)

优点:
  1. 无需关心元素范围:辅助数组法需要假设元素取值范围(如之前的 -1000~1000),set 可处理任意整数(正数、负数、超大数)。
  2. 代码简洁:无需手动设计去重逻辑,借助容器特性直接实现。
  3. 支持快速查找:如果后续需要判断某个元素是否存在,set 的查找效率(O (log n))远高于数组遍历(O (n))。
缺点:
  1. 空间开销略大:底层红黑树需要存储额外的结构(如指针、颜色标记),空间复杂度高于辅助数组(O (n) vs O (1))。
  2. 排序开销set 会自动排序,若场景不需要排序,会浪费少量性能(但对于 n≤1000 的题目,完全不影响)。

五、常见误区

  1. 不能直接修改 set 中的元素set 的元素是有序且唯一的,直接修改会破坏其结构,若需修改,需先删除旧元素,再插入新元素。
  2. set 的 size() 是无符号整数:若用 int 接收(如 int len = s.size()),在某些编译器下可能出现类型警告,可通过 (int)s.size() 强制转换。
  3. set 不支持随机访问:不能用 s[0] 访问第一个元素,必须通过迭代器 s.begin() 或范围 for 循环遍历。

总结

set 是 C++ 中处理 “去重”“统计不同元素”“快速查找” 的利器,核心记住:

  • 核心特性:自动去重 + 自动升序排序
  • 题目场景:统计不同元素个数 → 插入 set 后返回 size()
  • 时间复杂度:插入、查找、删除均为 O (log n),适合 n≤1e5 的场景(远超题目要求的 n≤1000)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值