面試題45:把數組排成最小的數
一、題目描述
輸入一個正整數數組,把數組裏所有數字拼接起來排成一個數,打印能拼接出的所有數字中最小的一個。例如輸入數組{3, 32, 321},則打印出這3個數字能排成的最小數字321323。
二、問題分析
之前我們做過字符全排列的習題 劍指Offer對答如流系列 - 字符串的排列,但是將算法思想應用到這一題的話,效果不好,求出所有的組合,再計算出組合的最小值,這效率該多低啊。
我們還要進一步探究,看看有沒有不錯的規律,供我們使用。
因爲數字拼接後的長度一樣,拼接後的結果大亦或是小 首先取決於最高位的數字,然後再低位。
既然這樣,我們定義一下數學模型:
對於數字m和n,可以拼接成mn和nm,如果mn<nm,我們定義m小於n。反之則相反。利用這個排序規則,從小排到大即可實現題目要求。
在求解的時候:拼接m和n,要考慮到大數問題,因此將m和n拼接起來的數字轉換成字符串處理。
使用 String.compareTo 方法:
compareTo() 的返回值是int, 它是先比較對應字符的大小(ASCII碼順序)
1、如果字符串相等返回值0
2、如果第一個字符和參數的第一個字符不等,結束比較,返回他們之間的差值(ascii碼值)(負值前字符串的值小於後字符串,正值前字符串大於後字符串)
3、如果第一個字符和參數的第一個字符相等,則以第二個字符和參數的第二個字符做比較,以此類推,直至比較的字符或被比較的字符有一方全比較完,這時就比較字符的長度.
三、問題解決
public String PrintMinNumber(int [] numbers) {
if(numbers==null || numbers.length<=0) {
return "";
}
ArrayList<String> list = new ArrayList<>();
for(int number:numbers) {
list.add(String.valueOf(number));
}
list.sort((s1, s2) -> {
String a = s1 + s2;
String b = s2 + s1;
return a.compareTo(b);
});
StringBuilder sb= new StringBuilder();
for(String str:list)
sb.append(str);
return sb.toString();
}