題目描述
輸入一個正整數數組,把數組裏所有數字拼接起來排成一個數,打印能拼接出的所有數字中最小的一個。例如輸入數組{3,32,321},則打印出這三個數字能排成的最小數字爲321323。
思路一:
排列出數組所有可能的組合,找出其中最小的數。難點在於求所有可能的組合,求解過程和求一串字符的字典序類似。如下所示:
(圖片來源於網絡)
僞代碼如下:
mothed(int[] arr, int start, int end)
tmp = min(arr, tmp);
for each i in [start, end]
swap(i, start);
mothed(start+1, end);
swap(i, start);
真實代碼如下:
public class Main {
static String min = null;
public static void main(String args[]) {
int[] arr = {3, 32, 321};
StringBuffer first = new StringBuffer();
for(int t : arr)
first.append(t);
min = first.toString();
findMin(arr,0, arr.length - 1);
System.out.println(min);
}
public static void findMin(int[] arr, int start, int end) {
if (start <= end) {
StringBuffer sb = new StringBuffer();
for (int k : arr)
sb.append(k);
if(min.compareTo(sb.toString()) > 0)
min = sb.toString();
for (int i = start; i <= end; i++) {
swap(arr, start, i);
findMin(arr, start + 1, end);
swap(arr, start, i);
}
}
}
public static void swap(int[] arr, int index1, int index2) {
int t = arr[index1];
arr[index1] = arr[index2];
arr[index2] = t;
}
}
算法特性:
空間複雜度較高,時間複雜度也高;
輸出:
321323
思路二:
從題目中可以發現: 以32 和 3 的組合爲例,要是排列後數最小,必須32 在 3 之前,同理 321 必須在 32 之前。那麼定義一種比較規則:
對於整數 x 和 y,xy表示x和y按順序拼接後的整數
if xy > yx , then x > y;
if xy < yx , then x < y;
else x = y;
於是思路就明瞭了,先利用Arrays.sort()按定義的比較規則對輸入數組進行排序,再將數組按次序拼接,得到的值即爲最小數。
public class Main {
public static void main(String args[]) {
Integer[] arr = {3, 32, 321};
Arrays.sort(arr, new Compare());
StringBuffer sb = new StringBuffer();
for (int i : arr)
sb.append(i);
System.out.println(sb);
}
}
class Compare implements Comparator<Integer> {
@Override
public int compare(Integer i1, Integer i2) {
return (String.valueOf(i1) + String.valueOf(i2)).compareTo(String.valueOf(i2) + String.valueOf(i1));
}
}
輸出:
321323
算法特性:時間複雜度相對較低O(nlogn),但是空間複雜度較高O(nlogn).
String.valueOf(i1) + String.valueOf(i2)先根據i1和i2生成兩個String對象,拼接在一起生成第三個String對象。每比較一次,均要生成多個String對象,因此空間複雜度爲O(nlogn).