三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

去重排序c++(绝非正解)

去重排序c++(绝非正解)

对于又要排序又要去重的基础题。比如

P1059 [NOIP 2006 普及组] 明明的随机数

题目描述

明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了NNN111100010001000之间的随机整数(N≤100)(N\leq100)(N100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。

输入格式

输入有两行,第111行为111个正整数,表示所生成的随机数的个数NNN

222行有NNN个用空格隔开的正整数,为所产生的随机数。

输出格式

输出也是两行,第111行为111个正整数MMM,表示不相同的随机数的个数。

222行为MMM个用空格隔开的正整数,为从小到大排好序的不相同的随机数。

输入输出样例 #1

输入 #1

10 20 40 32 67 40 20 89 300 400 15

输出 #1

8 15 20 32 40 67 89 300 400

说明/提示

NOIP 2006 普及组 第一题


这道题不难,代码也很短,但本人写起来觉得它很烦。为啥呢?因为用sort的话去重很烦(unique太难拼了,没学过的忽略这一句),手动排序——呃,谁学了sort之后还用手动排啊。

于是就这样,这道题很烦,归根结底,原因还是在于太老掉牙了(这种题没做过十次也有八次了)于是我今天分享一个新奇的方法。


首先,众所周知,c++里有一个STL容器叫set(集合)。
以下是它的自带函数:

函数作用
s.insert(val)插入元素 val;重复元素直接忽略
s.size()返回集合中元素个数(去重后的数量)
s.empty()集合为空返回 true,否则 false
s.clear()清空所有元素
s.find(val)查找 val,返回迭代器;找到→指向该元素;找不到→s.end()
s.erase(val)删除值为 val 的所有元素
s.erase(迭代器)删除迭代器指向的单个元素
s.begin()迭代器,指向最小元素(第一个)
s.end()尾后迭代器,不指向有效元素,遍历终止条件

核心特性

自动有序:

容器内部使用红黑树(平衡二叉搜索树)存储元素,默认从小到大升序排列

元素唯一(自动去重):

不能存

放重复值;
插入相同元素不会报错,但是插入无效

不支持随机访问:

不能用 s[0]、s[1] 下标取值,只能依靠迭代器遍历
迭代器双向遍历,只能 ++it、–it


简单来说就是这个东西可以自动排序去重,简直就是专门为这道题设计的。所以我们要做的就是: 输入 -> 输出。

#include<bits/stdc++.h>usingnamespacestd;intmain(){intn;cin>>n;set<int>s;for(inti=1;i<=n;++i){intx;cin>>x;s.insert(x);}cout<<s.size()<<endl;for(autoit=s.begin();it!=s.end();++it)cout<<*it<<" ";cout<<endl;return0;}

for (auto it = s.begin(); it != s.end(); ++it)这个是用迭代器遍历,没学过的就把这一句背下来并知道set只能用这个遍历就行了。(本文不负责讲解迭代器,若想详细学习,见《C++ STL迭代器完全指南:从原理到实战》)

所以我们用这段代码就能过这道题。是不是挺简便的。


本文到这里就差不多要结束了,多谢浏览。

← 返回列表