把数组排列成最小的数

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章