把数组排成最小的数

Posted by Dorck on March 19, 2023

本文是对于 常用排序算法合集 的扩展应用。

题目内容

把数组排成最小的数。要求如下:

输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。

附加说明:

  • 0 < nums.length <= 100

  • 输出结果可能非常大,所以你需要返回一个字符串而不是整数
  • 拼接起来的数字可能会有前导 0,最后结果不需要去掉前导 0

题意分析

首先写几条测试用例来带入实际场景看一下情况:

  • 输入 [2, 10, 6],输出拼接后的最小值是:1026
  • 输入 [48, 3, 305, 16],输出拼接后的最小值:16305348

由上可知,想要拼接得到最小值,只需要将数组中的元素按某种规律依次“从小到大”排列即可。值得注意的是,这里的“大小”并不是简单数值比较,而是与目标元素拼接后哪个较小。举个例子,数字 3 与数字 305 比较大小,正常来说 3 < 305 ,而在本题情境下,显然 305 应该排在 3 之前,因为 3305 > 3053。那么,我们不难得出以下结论:

  • 若 x + y > y + x,则 x “大于” y,本题情境下,y 应该排在 x 之前;
  • 若 x + y < y + x,则 x “小于” y,x 应排在 y 之前。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class Solution {
    public String minNumber(int[] nums) {
        String[] stringValues = new String[nums.length];
        for (int i = 0; i < nums.length; i++) {
            stringValues[i] = String.valueOf(nums[i]);
        }
        quickSort(stringValues, 0, stringValues.length - 1);
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < stringValues.length; i++) {
            stringBuilder.append(stringValues[i]);
        }
        return stringBuilder.toString();
    }

    private void quickSort(String[] array, int start, int end) {
        if (start >= end) return;
        int position = partition(array, start, end);
        quickSort(array, start, position-1);
        quickSort(array, position+1, end);
    }

    private int partition(String[] array, int l, int h) {
        // Last element as pivot.
        String pivot = array[h];
        int i = l;
        for (int j = l; j < h; j++) {
            String target = array[j];
            if ((array[j]+pivot).compareTo(pivot+array[j]) < 0) {
                if (i == j) {
                    // No need swapping.
                    ++i;
                } else {
                    // Need to move by exchange.
                    String temp = array[i];
                    array[i++] = target;
                    array[j] = temp;
                }
            }
        }
        String temp = array[i];
        array[i] = pivot;
        array[h] = temp;
        return i;
    }
}

复杂度分析

解题思路基于快排算法实现,所以平均时间复杂度为 O(NlogN),最坏退化为 O(N^2),空间复杂度为 O(N),以为内额外申请了一个大小为 N 的 stringValues 数组用于存放字符串。


许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。