题目链接
之前刷力扣貌似做过一样的题,当时直接看的题解,再次做这道题时只记得就是自定义排序方式而已,推了好一会排序比较方式才想起来正解是什么,所以还是自己写出来的印象深,只看题解的效果不如自己动脑想出来,叨叨完毕。
既然是贪心,就是想让两个数字组合起来的数字最小,所以只需要定义一种排序方式,把“小”的数字排在前面,“大”的数字排后面。
开始时想法是比较这俩数字字符串,同长度按字典序返回大小,长度不同时看短的那部分是否一样,不一样也是按字典序返回大小,一样就再比较长的字符串去掉相同部分剩余部分与前面重合部分循环比较……
之所以能得到上面讨论的那种排序准则,对于相同长度如9和8,我们很自然就知道89小于98,所以8要在9前面,正好和字典序相同,但是对于32和321,应该是321 32,而对于32和324,应该是32 324,为了寻找该怎么比较不同长度的字符串的大小,我们实则手动比较了a+b拼接和b+a拼接哪个更小,然后间接推导不同长度的字符串的大小比较准则。
事实上,自定义cmp函数的时候,可以直接用最根本的比较a+b和b+a谁更小,决定排序时是否交换a和b的顺序!(a和b都是string类型,所以+在这里是字符串的拼接)
要注意组成的数字前面的0不能输出出来,同时测试点2结果就是0,从第一个不为零的位置开始输出拼接结果的话对于答案就是0的情况就需要特判一下。
完整代码:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
string nums[10005];
bool cmp(string a,string b){
//直接比较两种拼接方式
//ab<ba就不交换顺序,反之就交换顺序
return a+b < b+a;
}
int main() {
#ifdef ONLINE_JUDGE
#else
freopen("1.txt","r",stdin);
#endif
int N;
cin >> N;
for(int i=0;i<N;i++){
cin >> nums[i];
}
sort(nums,nums+N,cmp);
string res="";
for(int i=0;i<N;i++)
res+=nums[i];
int i;//寻找第一个非0位置开始输出
for(i=0;i<res.size();i++){
if(res[i]!='0') break;
}
if(i==res.size()) cout << "0";//结果就是0 测试点2
for(;i<res.size();i++){
cout << res[i];
}
return 0;
}