P1012 拼数 ----sort的cmp写法精进+string比较思路优化

题目描述

设有 n 个正整数 a1…an,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。

输入格式

第一行有一个整数,表示数字个数 n。

第二行有 n 个整数,表示给出的 n 个整数 ai。

输出格式

一个正整数,表示最大的整数

输入输出样例

输入 #1

3
13 312 343

输出 #1

34331213

输入 #2

4
7 13 4 246

输出 #2

7424613

 

说明/提示

对于全部的测试点,保证 1≤n≤20,1≤ai≤10^9。

 

 

 


题解

哇,感觉这是我最近这段时间一来收获最多的一道单题。

因为只是接住了基础知识,具体实现思路都是自己写的。就很得劲。

 

这一看显然就是sort对string数组的排序

 

最初代码

#include<bits/stdc++.h>
using namespace std;

string s[30];

bool cmp(string a,string b)
{
	return a.compare(b);
}

int main()
{
	int n;
	
	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;
}

当时脑袋没有完全转过完来,谁知这反而引出了问题(其实明明可以先不写cmp,就从小到大排,然后倒着输出就好)

我这样写,样例1ok,但2却发生了错误。

 

理论上结果为 7424613,但实际...

???

思索后觉得是cmp比较函数写的有问题。

遂复习了下原理。

 

 

那么我的比较a.compare(b)的返回值又是怎么样的呢?

当a>b  返回正值

a==b 返回0

a<b  返回负值

 

等等,是当两个字符串a==b时,才返回0,二者不等时返回正数/负数。

我擦,找到问题了!!!

我把比较结果作为bool函数的返回值,我希望a>b时返回true,a<b时返回false。

但是实际上并不是这样,现在是只有当a与b相等时,才返回false,a与b不等就会返回true。

原来如此。

于是我修改了cmp函数。

bool cmp(string a,string b)
{
	int result = a.compare(b);        //记录比较的返回值
	if(result>=0)	return true;
	else		return false;
}

 

这样我得了75分。

还剩最后一个点。

 

后面的是我的程序输入+输出,前面的记事本是题目要求的输入+输出。

明显地可以看出不同,

我的程序:321 32

正确答案:32 321

 

想了以下,从追求数的大小来看,确实是这样。

我的问题:

当有两个字符串a,b,二者长度不同,但前面有一部分相同(且相同的部分就是那个短的字符串本身)。

按我的字符串比较,走完前面相同的,接下来比较时,b还有字符,但a已经没有了(看作那一位为'\0'),这样自然时b>a。

但在这里不行。

其实输入样例的后面还有一对,即135 和 13。

这部分我却没有排错。

我看出,除去前面的部分,长的字符串b的接下来的那一位要与短的a的开头那个字符进行比较。

对于321, 32  就是拿1与3比较,1<3,所以二者排序时把32放在了前面,成为32321。

对于135,13   就是拿5与1比较,5>1,所以把135放在了前面,成为13513。

 

遂重写cmp。

这一次我总算完全搞懂了cmp的原理和写法(因为我写了好多呀)

bool cmp(string a,string b)
{
	int size_a=a.size(),size_b=b.size();
	for(int i=0;i<min(size_a,size_b);i++)    //前面的部分
	{
		if(a[i]>b[i])	return 1;
		else if(a[i]==b[i])	continue;
		else	return 0;
	}
	if(size_a==size_b)	return 1;
	//前面都一样,后面长度不同
	if(size_a<size_b)	//a走完了,b还有 
	{
		if(b[size_a]>a[0])	return 0;
		else	if(b[size_a]<a[0])	return 1;	
	}
}

 

 

ac代码

#include<bits/stdc++.h>
using namespace std;

string s[30];

bool cmp(string a,string b)
{
	int size_a=a.size(),size_b=b.size();
	for(int i=0;i<min(size_a,size_b);i++)
	{
		if(a[i]>b[i])	return 1;
		else if(a[i]==b[i])	continue;
		else	return 0;
	}
	if(size_a==size_b)	return 1;
	//前面都一样,后面长度不同
	if(size_a<size_b)	//a走完了,b还有 
	{
		if(b[size_a]>a[0])	return 0;
		else	if(b[size_a]<a[0])	return 1;	
	}
}

int main()
{
	int n;
	
	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;
}

 

 

补充:

我再后来翻看大佬的思路时,惊奇的发现原来有很简洁的cmp。

bool cmp(string a,string b)
{
    return a+b>b+a;
}

啊这...我服啦(写了那么多代码的我留下了眼泪)

 

而且,string可以直接比较啊喂

当涉及string 的直接比较时,用比较运算符就行啦,也就是>、<、==、>=、<=、!= 等。

当然这也不是说a.compare(b)没用,它是支持多参数的,当我对比较有严格要求时,就要用它了。

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值