2022.11.17排序题讲解

T1-明明的随机数

排序 + 去重

显然,对于去重来说,桶排序无疑是一种好的方式,对于此题的数据范围完全够用。

#include<bits/stdc++.h>
using namespace std;
int x[101],a[1001] = {0};
int main(){
    int n;
    scanf("%d",&n);
    int maxx = -0x3f3f3f; 
    for(int i = 0;i < n;i++){
    	scanf("%d",&x[i]);
    	a[x[i]] ++;
    	maxx = max(maxx , x[i]);
	}
	int ans = 0; 
	for(int i = 0;i <= maxx;i++){
		if(a[i] > 0){
			ans++;
		}
	}
	printf("%d\n",ans);
	for(int i = 0;i <= maxx;i++){
		if(a[i] > 0){
			printf("%d ",i);
		}
	}
	return 0;
}

然而,使用C++自带库函数也十分简单

#include<bits/stdc++.h>
using namespace std;
int a[1001];
int main(){
    int n;
    scanf("%d",&n);
    for(int i = 1;i <= n;i++){
    	scanf("%d",&a[i]);
	}
	sort(a + 1,a + n + 1);
	int ans = unique(a + 1,a + n + 1) - a - 1;
	printf("%d\n",ans);
	for(int i = 1;i <= ans;i++){
		printf("%d ",a[i]);
	}
	return 0;
}

注意:unique:将数组中不重复元素前移

T2: 简单冒泡+判断次数

Q:为什么能保证【移动次数最小】?

A:冒泡排序的每一次交换都是必要的。

T3: masses number:建议使用桶排序

T4: knumber:可以使用STL中nth_element()函数

        nth_element(a,a+2,a+9),将下标为2,也就是第3个数放在正确的位置,求的是第3小的数a[2]。(下标从零开始,返回第i+1小)

        nth_element(a,a+k,a+n),函数把下标为k的元素放在了正确位置,对其它元素并没有排序,当然k左边元素都小于等于它,右边元素都大于等于它,所以可以利用这个函数快速定位某个元素

        nth_element(a,a+2,a+9,comp)

        nth_element()为什么快呢:因为没排序

        注意特判

T5≈T4

T6:scholar 没什么好讲的

T7:  这道题你也想用桶排吗??

       1.5*10^9……

       直接sort(long long*)就成(对于时间限制没那么高)

T8,T9(重头戏)

对于T8-> 使用“数学方法”证明取中位数时有最小和。

对于T9-> x,y分开判断。

纵向与T8类似

横向:

先对所有的X坐标从小到大排序,排序后,为了放便描述,我们依然用X1,X2,X3……Xn-1,Xn代表士兵的位置(但是要注意这个是已经排好序的),假如最后所有士兵站的位置为X,X+1,X+2……X+n-1,那么即是求|X1-X|+|X2-(X+1)|+|X3-(X+2)|+……|Xn-(X+n-1)|的最小值,将算式变形,即为|X1-X|+|(X2-1)-X|+|(X3-2)-X|+……|(Xn-(n-1))-X|,同上可以看出,X即为X1,X2-1,X3-2……Xn-(n-1)的中位数,据此可以求得X方向的最小移动步数。

 

 T9代码

#include<bits/stdc++.h>
using namespace std;
int posx[10005];
int posy[10005];
int main(){
    int n;
    while (scanf("%d",&n)!=EOF){
        for (int i=0;i<n;i++){
            scanf("%d%d",&posx[i],&posy[i]);
        }
        sort(posx,posx+n);
        sort(posy,posy+n);
        for (int j=0;j<n;j++){
            posx[j] = posx[j] - j;
        }
        sort(posx, posx + n);
        int mx = posx[n / 2];
        int my = posy[n / 2];
        int count = 0;
        for (int k = 0; k < n; k++){
            count = count + abs(posx[k] - mx); 
            count = count + abs(posy[k] - my); 
        }
        printf("%d",count);
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值