CSP_201503-2_数字排序

文章介绍了一种使用C++编程的方法,通过结构体存储整数及其出现次数,利用sort()函数和自定义比较函数cmp_cnt进行排序。当出现次数相同时,依据数值大小决定顺序。程序还统计了不重复的数的个数,并依次输出排序后的结果。

问题描述

在这里插入图片描述

思路

  1. 使用结构体,其中定义两个成员变量,一个代表整数本身,一个代表该数出现的次数。
struct node{
	int pos;//记录数字
	int cnt=0;//初始化出现次数
}a[maxn];
  1. 使用C++自带的sort()函数对结构体根据次数大小进行排序,在此需要按照题目要求自定义排序规则。

题目要求: 按出现次数递减的顺序输出。如果两个整数出现的次数一样多,则先输出值较小的,然后输出值较大的。

bool cmp_cnt(node a,node b)
{
	if(a.cnt == b.cnt)
        return a.pos < b.pos;
	return a.cnt > b.cnt;
}

关于sort()函数可以参考这篇博客:sort()函数

  1. 使用数组 vis[] 对已经出现过的数进行标记,从而统计不重复的数的个数。

完整代码

#include<iostream>
#include<algorithm>
using namespace std;

const int maxn = 1010;
int vis[maxn] = {0};

struct node{
	int pos;//记录数字
	int cnt=0;//初始化出现次数
}a[maxn];

bool cmp_cnt(node a,node b)
{
	if(a.cnt == b.cnt)
        return a.pos < b.pos;
	return a.cnt > b.cnt;
}

int main(){
    int i, n, x;
    int sum = 0;    //统计有多少个不重复的个数

    cin >> n;
    for(i=0;i<n;i++)
	{
		cin >> x;
		if(vis[x]==0)
		{
			sum++;
			vis[x]=1;
		}
		a[x].pos=x;
		a[x].cnt++;
	}

    sort(a, a+maxn, cmp_cnt);

    for( i = 0; i < sum; i++){
        cout << a[i].pos << ' ' << a[i].cnt << endl;
    }

    return 0;
}

提交记录

在这里插入图片描述

### 题目相关背景 插入排序是一种常见且简单的排序算法。假设比较两个元素的时间为 $O(1)$,插入排序可以以 $O(n^2)$ 的时间复杂度完成长度为 $n$ 的数组排序。不妨假设这 $n$ 个数字分别存储在 $a_1, a_2, \ldots, a_n$ 之中 [^2][^3]。 ### 代码实现 ```cpp #include <bits/stdc++.h> using namespace std; int b[8005];//保存排序后的位置 struct node { int a;//数值 int w;//原来的位置 }a[8005]; int main() { int n,q; scanf("%d %d",&n,&q); for (int i=1;i<=n;i++){ scanf("%d",&a[i].a); a[i].w=i; } for (int i=1;i<=n;i++){//做一次插入排序 for (int j=i;j>=2;j--){ if (a[j].a<a[j-1].a){ swap(a[j],a[j-1]); }else{//加入break可以节省时间 break; } } } for (int i=1;i<=n;i++){//把排序后的位置存到b数组里 b[a[i].w]=i; } for (int i=1;i<=q;i++){ int t; scanf("%d",&t); if (t==1){//操作1 int x, v; scanf("%d %d", &x, &v); a[b[x]].a = v;//更新a数组的值 for (int k = 2; k <= n; k++) {//做逆插入排序 for (int j = k; j >= 2; j--) { //按值的大小排序,值相同的按原来的位置排序 if (a[j].a < a[j - 1].a || a[j].a == a[j - 1].a && a[j].w < a[j - 1].w) { swap(a[j],a[j-1]);//交换 swap(b[a[j].w],b[a[j-1].w]);//将b数组中的位置也做下交换 } else { break;//break可以节省时间 } } } } else { int x; scanf("%d", &x); printf("%d\n", b[x]); } } return 0; } ``` 不加 `break`,理论上只能过 9 个点(36 分) [^1]。 ### 解题思路 - 首先读取输入的数组元素和询问次数。 -数组进行一次插入排序,在排序过程中加入 `break` 语句可节省时间。 -排序后的元素位置存到 `b` 数组中。 - 对于每次询问,若为操作 1,则更新数组元素的值,并进行逆插入排序,同时更新 `b` 数组;若为操作 2,则输出指定元素排序后的位置。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值