题目描述:给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数
实例一:输入: [10,2] 输出: 210
实例二:输入: [3,30,34,5,9] 输出: 9534330
在这道题上花费的时间比较多,主要是考虑问题的总是不够全面,提交了很多次都没有通过。
一开始的思路是,让每两个数进行比较,当然肯定不是直接比较,比如说5和21比较,后者大,但是需要将5排在前面。所以很容易想到比较第一位。那么如果第一位相同,第二位不同;前两位相同第三位不同呢,等等等等。所以我想到的是先将两个数字补充为同样位数的再进行比较。比如5和21,我先将5换成50,再与21进行比较。很快,一顿操作猛如虎,完成了测试代码,提交后发现并没有通过。测试代码为[12,121],按照我的逻辑,进行比较的数为120和121,由于121大,所以将121放在前面,组合出来的数为12112,显然,这个数肯定比12121小。瞬间有种被KO的感觉。
接着,调整一下思路,干脆直接将两个数直接拼接了再进行比较,比如A和B进行比较,先拼接成AB和BA,再将AB和BA进行大小比较。由于数字溢出最大值,所以肯定是将拼接后的字符串转换成char数组,然后再用每位上的char进行大小比较。
实例代码如下:
/**
* 给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。
*/
public class LeeCode179 {
public String largestNumber(int[] nums) {
String largestNumberString = "";
for (int i = 0, len = nums.length; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
if (numComp(nums[i], nums[j])) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}
//防止[0,0]
if(nums[0]==0){
return "0";
}
for (int num : nums) {
largestNumberString = largestNumberString + num + "";
}
return largestNumberString;
}
/**
* 将两个数字补齐为同样位数后再比较大小
* @param num1
* @param num2
* @return
*/
private boolean numComp(int num1, int num2) {
boolean changeOrNot = false;
//当需要调换两个元素顺序时,返回true
String str1 = Integer.toString(num1)+Integer.toString(num2);
String str2 = Integer.toString(num2)+Integer.toString(num1);
char[] chars1 = str1.toCharArray();
char[] chars2 = str2.toCharArray();
//比较两个数组对应位大小
for(int i=0,len=str1.length();i<len;i++){
if(chars1[i]<chars2[i]){
return true;
}else if(chars1[i]>chars2[i]){
return false;
}
}
return changeOrNot;
}
}
建议根据思路再手动编辑代码,因为自己也在调试过程中遇到了很多考虑不全面,或者思维局限的地方。比如针对测试数据[0,0],如果在按照之前的逻辑操作下来,返回的字符串结果就是 00 ,不符合要求,于是在输出前可以加上一个对首位的判断。
到了这里,本该漏出一丝惬意的笑容,可惜,执行时间和消耗内存方面双双没有什么优势,于是瞻仰了一下官方的示例代码。官方的思路更加简单清晰一些,先是将int类型的数组一次性转换为String类型的数组,然后使用自定义的数组排序工具进行自动排序,然后再按顺序将排序后的String通过字符串拼接,打印出结果。这种方法确实高效很多,特别是数据更大的时候。同时,排序之前的一些预处理,或者说是特殊情况特殊处理,也能有效减少一些无必要流程的执行判断。
官方实例代码如下:
public class LeeCode179Standard {
public String largestNumber(int[] num) {
if (num.length == 0) {
return "";
}
if (num.length == 1) {
return Integer.toString(num[0]);
}
String[] str = new String[num.length];
for (int i = 0; i < num.length; i++) {
str[i] = Integer.toString(num[i]);
}
Arrays.sort(str, new StringComparator());
StringBuilder sb = new StringBuilder("");
for (int i = num.length - 1; i >= 0; i--) {
sb.append(str[i]);
}
if (sb.charAt(0) == '0') {
return "0";
}
return sb.toString();
}
class StringComparator implements Comparator<String> {
public int compare(String s1, String s2) {
if (s1.length() == 0 && s2.length() == 0) {
return 0;
}
if (s2.length() == 0) {
return 1;
}
if (s1.length() == 0) {
return -1;
}
for (int i = 0; i < s1.length() && i < s2.length(); i++) {
if (s1.charAt(i) > s2.charAt(i)) {
return 1;
} else if (s1.charAt(i) < s2.charAt(i)) {
return -1;
}
}
if (s1.length() == s2.length()) {
return 0;
}
if (s1.length() > s2.length()) {
if (s1.charAt(0) < s1.charAt(s2.length())) {
return 1;
} else if (s1.charAt(0) > s1.charAt(s2.length())) {
return -1;
} else {
return compare(s1.substring(s2.length()), s2);
}
} else {
if (s2.charAt(0) < s2.charAt(s1.length())) {
return -1;
} else if (s2.charAt(0) > s2.charAt(s1.length())) {
return 1;
} else {
return compare(s1, s2.substring(s1.length()));
}
}
}
}
}