排序题技巧刷题记录一


前言

本文于短学期开始第一天,通过复习前面所学以及在洛谷上刷题进行记录一些目前没学到或者不熟练的知识点,以此来记录学习历程供以后反复复习使用。知识点容易遗忘,但是反复复习就能形成长期记忆啦!

一、P1012 [NOIP1998 提高组] 拼数

在这里插入图片描述
解题的初步思路:
想将每一个数字的最高位就进行比较后在进行排序后输出,但是想到每个数字的位数不确定,用int型取余的话运算量较大;如果用string的话可能会比较容易一些…

#include<iostream>
#include<string>
#include<algorithm>//sort()函数的头文件
using namespace std;
string s[25];//数组比最大数据大,防止数据溢出,同时定义在全局里面进行默认初始化
int n;

bool cmp(string a,string b) {
	return a+b>b+a;
}
/*不要直接这样定义
bool cmp(string a,string b) {
	return a>b;
}
这样会出现321>32但是32132<32321,还是有特殊情况未能达到目标排序效果
*/
int main() {
	cin>>n;
	for(int i=1; i<=n; i++) cin>>s[i];
	sort(s+1,s+n+1,cmp);//直接进行排序,默认升序排序(点睛之笔)
	for(int i=1; i<=n; i++) cout<<s[i];//最后直接输出就好了
	return 0;
}

这个解题思路是参考大佬的解题思想( ~ - ~ )
这里巧妙运用了sort()函数以及重定义cmp()函数

小知识点记忆:

1.sort函数

头文件#include< algorithm >
形参(start,end,cmp)
start为排序起始地址,end为数组结束的下一位地址,cmp为规定排序的方法,可以不填,默认为升序
作用机理类似于快排,时间复杂度为n*log2n

2.cmp函数

自定义的排序,这里不能仅仅简单的比较输入的两个字符串的大小,而是要比较两个字符串相加所得的数哪一个更大。

二、P1055 [NOIP2008 普及组] ISBN 号码

在这里插入图片描述
初步解题思路:
用char数组储存每一个元素,出去所有的‘-’符号,其它的数据转化为数字后按照题目的运算进行相加。但是忽略了尾部标识码为10的情况。(这里不充知识点标识符为Ⅹ则表示10)尾部标识符为x时不能直接减去‘0’转化为10进行比较…

#include<iostream>
#include<cstdio>
using namespace std;
int main() {
	char a[14],mod[12]="0123456789X";//x表示10,用mod储存运算的余数,mod运算是求除以11所得的余数
	scanf("%s",&a);//以字符串的形式输入,因为C/C++数组会在末尾自动补'\0',故要大一位
	int t=1,s=0;
	for(int i=0;i<12;i++)
	if(a[i]>='0'&&a[i]<='9'){
		s+=(a[i]-'0')*t;
		t++;
	}
	if(mod[s%11]==a[12])
	    cout<<"Right";
	else{
		a[12]=mod[s%11];
		printf("%s",a);
	}
    return 0;
}

小知识点记忆:

1.x的寓意

x在身份证等地方表示10

2.mod运算

这里的mod是储存的一个数除以11后取余的结果
mod函数的使用:
mod(x,y)表示的是x除以y后的余数且结果符号与y一致
特殊情况:mod(x,0)结果为x;mod(x,x)结果为0

三.P5143 攀爬者

在这里插入图片描述
初步解题思路:
先建立一个二维数组或者结构体或者类来储存坐标的三个值,如果用二维数组则需要进行嵌套循环交换三个数据进行排序,显然时间复杂度很大(最初试过,最后三组数据超时)。用结构体或者类来储存则可以直接重载<运算符,再利用sort函数进行排序,这样大大减小了时间复杂度,就不会超时啦!(>-<)

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
class point
{
public:
    int x;
    int y;
    int z;
    bool operator<(const point& P)const {//重载小于运算符
        return z < P.z;
    }
};
int main()
{
    int n;
    scanf("%d", &n);
    point a[n];
    for (int i = 0; i < n; i++)
        scanf("%d %d %d", &a[i].x, &a[i].y, &a[i].z);
    sort(a, a + n);
    double s=0;
    for (int i = 0; i < n-1; i++) 
        s += sqrt(pow(a[i + 1].x - a[i].x, 2) + pow(a[i + 1].y - a[i].y, 2) + pow(a[i + 1].z - a[i].z, 2));
    printf("%.3lf", s);
    return 0;
}

这一题没有什么很重要的知识点啦,但是需要把以前所学以及平常所学小的语法点都灵活贯通,运用起来!

总结

今天完成了之前一段时间没有完成的洛谷排序题单,虽然题目都很简单,但是看得出来以前学习的只是还没有能完全灵活运用导致做题速度不够快,思维不够敏捷,在接下来的几天也要多找找排序的题目不断巩固。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值