welcome to my blog
剑指offer面试题45(java版):把数组排成最小的数
题目描述
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
思路
- 需要额外考虑的一个问题:m和n都在int型能表达的范围内,但它们拼接起来的数字mn和nm用int型表示就有可能溢出了,所以这还是一个隐形的大数问题
- 两个数字a,b, 把a放在b的左边, 当且仅当str(a)+str(b) < str(b)+str(a)
笔记
- 字符串String自身实现了Comparable接口中的compareTo()方法, 默认是自然排序
- 如果我们需要自定义排序, 则需要继承Comparator接口并实现compare()方法
- 使用Collections的静态方法sort()对List集合进行排序
- Collections.sort(List list, Comparator<? super T> c)
Collections.sort(al, new Comparator<Integer>(){
public int compare(Integer t1, Integer t2){
String str1 = ""+t1+t2;
String str2 = ""+t2+t1;
return str1.compareTo(str2);
}
});
- 我开始弄错了, 想用Arrays.sort(T[] a, Comparator<? super T> c)对arr进行排序, 问题是:arr是int[]类型的, 但是泛型中不能用int!
- 所以得用Collections.sort()对集合进行排序(可以将int[]转成Integer[])
- ArrayList al = new ArrayList();可以添加int型, 添加进al后就变成Integer型了
第三次做, 巩固java基础, 字符串比较要用str.compareTo(); 通过字典序比较两个整数的大小时要保证两个整数的位数一样, 比如"323"与"332"按照字典序比较可以, 但是"323"与"33"按照字典序比较的结果就是错误的
class Solution {
public String minNumber(int[] nums) {
int n = nums.length;
String[] strs = new String[n];
for(int i=0; i<n; i++){
strs[i] = String.valueOf(nums[i]);
}
Arrays.sort(strs, new Comparator<String>(){
public int compare(String s1, String s2){
//两个字符串长度一样, 此时字典序等于数值序
return (s1+s2).compareTo(s2+s1);
}
});
StringBuilder sb = new StringBuilder();
for(String s : strs){
sb.append(s);
}
return sb.toString();
}
}
import java.util.Arrays;
import java.util.Comparator;
public class Solution {
public String PrintMinNumber(int [] numbers) {
if(numbers==null||numbers.length==0)
return ""; //返回形式和面试官商量
Integer[] arr = new Integer[numbers.length];
for(int i=0; i<arr.length; i++)
arr[i] = numbers[i];
Arrays.sort(arr, new Comparator<Integer>(){
public int compare(Integer o1, Integer o2){
//通过字典序比较两个整数的大小时要保证两个整数的位数一样
//"323"与"332"按照字典序比较可以, 但是"323"与"33"按照字典序比较的结果就是错误的
return (""+o1+o2).compareTo(""+o2+o1);
}
});
//这里最好用StringBuilder, 节省字符串常量池空间
String res="";
for(int i=0; i<arr.length; i++)
res+=arr[i];
return res;
}
}
第二次做,主要是要知道比较的定义要满足自反性,对称性,传递性;看上面的笔记
- 巩固基础int[] → Integer[]; int → String; String → int
1 ) 自反性: x , y 的比较结果和 y , x 的比较结果相反。
2 ) 传递性: x > y , y > z ,则 x > z 。
3 ) 对称性: x = y ,则 x , z 比较结果和 y , z 比较结果相同
import java.util.Arrays;
import java.util.Comparator;
public class Solution {
public String PrintMinNumber(int [] numbers) {
if(numbers==null||numbers.length==0)
return "";
//
Integer[] arr = new Integer[numbers.length];
for(int i=0; i<arr.length; i++)
arr[i] = numbers[i];
Arrays.sort(arr, new Comparator<Integer>(){
public int compare(Integer t1, Integer t2){
String s1 = String.valueOf(t1);
String s2 = String.valueOf(t2);
return Integer.valueOf(s1+s2) - Integer.valueOf(s2+s1);
}
});
String res = "";
for(int i=0; i<arr.length; i++)
res += String.valueOf(arr[i]);
return res;
}
}
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Collections;
public class Solution {
public String PrintMinNumber(int [] numbers) {
/*
排序原则
a在b的左边意味着: str(a)+str(b)<str(b)+str(a)
注意证明过程中的传递性证明
*/
ArrayList<Integer> al = new ArrayList<Integer>();
for(int i=0; i<numbers.length; i++)
al.add(numbers[i]);
// sort(List<T> list, Comparator<? super T> c)
Collections.sort(al, new Comparator<Integer>(){
public int compare(Integer t1, Integer t2){
String str1 = ""+t1+t2;
String str2 = ""+t2+t1;
return str1.compareTo(str2);
}
});
/*
不能直接用return al.toString(); 因为AbstractCollection类的toString()方法如下:
返回此 collection 的字符串表示形式。该字符串表示形式由 collection 元素的列表组成,
这些元素按其迭代器返回的顺序排列,并用方括号 ( "[]") 括起来。
相邻元素由字符 ", "(逗号加空格)分隔。通过 String.valueOf(Object) 可以将元素转换成字符串。
*/
String res="";
for(int i:al)
res += Integer.toString(i);
return res;
}
}