题目描述
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{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).