C语言去重
C语言实现去重 升序排序输出
1.前几天一哥们面试题,让从1-1000序号中随机选取7个数作为年终颁奖名额,其中一个人不能重复领奖,,,,这就是明显的去重操作 ,,,当时用Java写的Set集合
小明公司有1000人,今年年会举行抽奖活动,一次抽出三等奖4名,二等奖2名,一等奖1名
https://blog.csdn.net/qq_45896330/article/details/122971352
2.最近几天又有小伙伴搞C语言问一位数组怎么去重
排序去重思路
首先对这个数据进行排序(本人比较喜欢冒泡排序),然后比较相邻的是否存在重复
如果存在重复3种方案
方案一:(巧妙法)在输出的时候进行判断相同的元素只输出一次
方案二:引入新的数组,排序后的数组比较相邻的元素,如果相同只把一个放入新数组
方案三:在原来数组上把重复的给删除
其实还有很多方法(比如桶排序的思想,把相同的数放在同一桶里面,最后输出的时候直接判断桶中书否有数,有的话直接输出一次下标,根据题意如果数组中数的范围比较小可以采用,但是书比较大的时候就比较浪费空间了,毕竟数组申请连续的内存空间是很浪费资源的),相对来说比较麻烦第一种方案比较好一点如果是只是去重的话,可以采用类似方法一的技巧
2.1方法一(巧妙法)在输出的时候进行判断相同的元素只输出一次
先排序,再去重
//数组去重后 升序输出
#include<stdio.h>
void Sort(int a[],int n);
int main(){
int n,i,j;
int a[10];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
Sort(a,n);
printf("%d",a[0]);
for(int j = 0; j < n-1; j++) {
if(a[j]!=a[j+1]){ //如果后边的不等于前面的就把后边的数输出
printf(" %d",a[j+1]);
}
}
}
void Sort(int a[],int n){ //冒泡排序(升序)每次把最大的元素放在后边
for(int i=0;i<n-1;i++){
int flag=0; //冒泡排序的截止条件(如果一个数组本来就是有序的就直接终止排序)
for(int j=0;j<n-i-1;j++){ //每次排序后边的都拍好一个元素,下次就少比较一次
if(a[j]>a[j+1]){
flag=1;
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
if(flag==0){
break; //提前终止
}
}
}
输入
10
1 2 3 4 5 4 3 2 9 1
输出:
1 2 3 4 5 9
2.2方案二:引入新的数组,排序后的数组比较相邻的元素,如果相同只把一个放入新数组
先排序 再去重
//数组去重后 升序输出
#include<stdio.h>
void Sort(int a[],int n);
int main(){
int n,i,j;
int a[10];
int arr[10];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
Sort(a,n);
int l = 0; //记录新数组的下标
//printf("%d",a[0]);
arr[0]=a[0];
for(int j = 0; j < n-1; j++) {
if(a[j]!=a[j+1]){ //如果后边的不等于前面的就把后边的数输出
//printf(" %d",a[j+1]);
arr[++l]=a[j+1];
}
}
printf("%d",arr[0]);
for(int i=1;i<=l;i++){ //此时的l 表示的下标不是长度 此时可以为等号
printf(" %d",arr[i]);
}
}
void Sort(int a[],int n){ //冒泡排序(升序)每次把最大的元素放在后边
for(int i=0;i<n-1;i++){
int flag=0; //冒泡排序的截止条件(如果一个数组本来就是有序的就直接终止排序)
for(int j=0;j<n-i-1;j++){ //每次排序后边的都拍好一个元素,下次就少比较一次
if(a[j]>a[j+1]){
flag=1;
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
if(flag==0){
break; //提前终止
}
}
}
测试输入:
10
1 2 1 0 5 3 2 0 7 9
结果输出:
0 1 2 3 5 7 9
2.3方案三:在原来数组上把重复的给删除
这个方法是最麻烦的方法,数组是以下标索引的,前边删除一个元素后边的元素都需要往前移动一位
先排序,再去重
//数组去重后 升序输出
#include<stdio.h>
void Sort(int a[],int n);
int main(){
int n,i,j;
int a[10];
int arr[10];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
Sort(a,n);
for(i = 0; i < n-1; i++) {
if(a[i]==a[i+1]){ //后一个元素是否等于前一个元素,是的话把后边的元素覆盖掉
for(j=i+1;j<n-1;j++){
int temp = a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
n--; // 覆盖掉一个元素,数组总长度-1
i--; //重新比较这个位置上的元素和覆盖的元素 1 1 1 3(当i=0时a[0]=a[1]会把a[1]给覆盖掉,1 1 3覆盖的元素还是1还需要比较,此时要退回来再比较覆盖后的元素)
}
}
printf("%d",a[0]);
for(int i=1;i<n;i++){
printf(" %d",a[i]);
}
}
void Sort(int a[],int n){ //冒泡排序(升序)每次把最大的元素放在后边
for(int i=0;i<n-1;i++){
int flag=0; //冒泡排序的截止条件(如果一个数组本来就是有序的就直接终止排序)
for(int j=0;j<n-i-1;j++){ //每次排序后边的都拍好一个元素,下次就少比较一次
if(a[j]>a[j+1]){
flag=1;
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
if(flag==0){
break; //提前终止
}
}
}
测试输入:
10
0 0 0 3 5 0 1 1 1 0
结果输出:
0 1 3 5
2.4只去重 不排序
(重复的保留后边的)
- 直接双重循环比较第一个元素与后边所有元素是否重复,若重复直接跳过输出,不重复输出
- 然后比较第二个元素与后边所有元素是否重复,若重复直接跳过,不重复输出
- 最终的话,会输出每个重复元素的最后一个元素
//数组去重后
#include<stdio.h>
int main(){
int n,i,j;
int a[10];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
//不排序直接去重
for(int i = 0; i < n; i++) {
bool flag = false;
for(int j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
flag = true; //比较前边的元素和后边的元素是否相同,,,相同的话跳过不输出,,,(相当于重复的输出最后一个)
break; //只要发现有一个重复的就没必要继续比下去了,直接终止本次循环
}
}
if(!flag) {
printf("%d ", a[i]);
}
}
}
测试输入:
10
1 2 1 1 0 5 0 6 3 4
结果输出:
2 1 5 0 6 3 4这种去重的思想和插入排序差不多,时间复杂度都是O(n2),插入的话是每次比较后找到自己合适的位置放下,这个是从前往后找与自己相同的元素,找到就跳过输出下一位,找不到就输出