问题描述
给定一些字符串(只包含小写字母),要求将他们串起来构成一个字典序最小的字符串。
输入格式
第一行T,表示有T组数据。
接下来T组数据
每组第一行一个正整数n,表示字符串个数。
接下来n行,每行一个字符串(长度不超过100)。
输出格式
T行,每行一个字符串。
样例输入
1
3
a
b
c
样例输出
abc
数据规模和约定
T<=7000,n<=100;
思路:我最开始想的直接用Arrays.sort()排个序就行了,在蓝桥杯测试了一遍发现出错,原来是没考虑到还要比较拼接在一起的情况,例如:
ba和b排序后是b, ba,但是拼在一起时bba>bab不满足字典序最小的情况,所以我们还需要考虑拼接后的字典序。
我这里是用冒泡排序考虑拼接后字典序的情况:
就是在b,ba的基础上再次判断,得到b,ab的情况
for (int i=0;i<str.length-1;i++){
for (int j=0;j<str.length-i-1;j++){
String k1 = str[j]+str[j+1]; // 先按不同顺序拼接字符串
String k2 = str[j+1]+str[j]; // 以便比较哪种拼接方式字典序最小
if (k1.compareTo(k2)>0){ // 若k1的字典序大于k2,则应交换str[j]和str[j+1]的位置
String temp=str[j]; // 来使最后拼接后的字典序最小
str[j] = str[j+1];
str[j+1] = temp;
}
}
}
得了90分,最后一个测试用例规模太大,导致超时,并且内存超限,仔细一想应该是冒泡排序复杂度太高O(n平方),内存超限应该是数组消耗空间太大,可以考虑选择更好的方法比较两个串拼在一起的方式的字典序大小,存储字符串的空间也可以用List或者Set来减少内存开销。大家可以根据我的代码做出改进,对于只想混个省二的我就不去尝试了。
完整代码:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt(); // 接收数据的组数
while (a>0){ // 控制操作次数,即操作a组数据后就结束
int n = sc.nextInt(); // 字符串的个数
String[] s = new String[n]; // 创建数组保存字符串
sc.nextLine(); // 当上一行接收数字,下一行接收字符串时,用sc.nextLine()消除回车的影响
for (int i=0;i<n;i++)
s[i] = sc.nextLine(); // 将字符串存入数组
Arrays.sort(s); // 先按字典序由小到大排
solve(s); // 再在各个字符串字典序由小到大的情况下操作,获得结果
a--;
}
}
private static void solve(String[] str){ //操作拼接后的情况,来在之前的基础上排序
for (int i=0;i<str.length-1;i++){
for (int j=0;j<str.length-i-1;j++){
String k1 = str[j]+str[j+1]; // 先按不同顺序拼接字符串
String k2 = str[j+1]+str[j]; // 以便比较哪种拼接方式字典序最小
if (k1.compareTo(k2)>0){ // 若k1的字典序大于k2,则应交换str[j]和str[j+1]的位置
String temp=str[j]; // 来使最后拼接后的字典序最小
str[j] = str[j+1];
str[j+1] = temp;
}
}
}
for (String s : str)
System.out.print(s); // 输出结果
System.out.println();
}
}