题目

剑指 Offer 45. 把数组排成最小的数

思路1

  • 将整数数组转化成字符串数组
  • 然后使用Arrays工具类的sort方法帮助我们排序

代码

class Solution {
    public String minNumber(int[] nums) {
        int length = nums.length;

        // 将整数数组转化成字符串数组
        String[] str = new String[length];
        for (int i = 0; i < length; i++) {
            str[i] = String.valueOf(nums[i]);
        }

        // 使用Java自带排序
        Arrays.sort(str, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return (o1+o2).compareTo(o2+o1);
            }
        });

        // 将字符串数组里的按顺序拼接
        StringBuilder sb = new StringBuilder();
        for (String s : str) {
            sb.append(s);
        }

        return sb.toString();
    }
}

复杂度分析

  • 时间复杂度:\(O(NlogN)\)
  • 空间复杂度:\(O(N)\)

思路2

  • 自定义排序规则
  • 可以使用冒泡排序比较好理解一点,也可以使用快速排序
  • 排序规则是这样的,通过拼接字符串拼接xy:
    • 如果x+y > y+x,那么说明x大于y
    • 如果x+y < y+x,那么说明x小于y
  • 按照这个排序规则,可以得出类似升序排序,升序排序是前面的数字要小于后面的数字,这个题目也是要求前面的数字在该题环境下要小于后面的数字
  • 因此我们可以得出以下代码:

代码

class Solution {
    public String minNumber(int[] nums) {
        int length = nums.length;

        // 将整数数组转化成字符串数组
        String[] str = new String[length];
        for (int i = 0; i < length; i++) {
            str[i] = String.valueOf(nums[i]);
        }

        // 自定义排序规则的快速排序
        quickSort(str, 0, length-1);

        // 将字符串数组里的按顺序拼接
        StringBuilder sb = new StringBuilder();
        for (String s : str) {
            sb.append(s);
        }

        return sb.toString();
    }

    public void quickSort(String[] arr, int left, int right) {
        String pivot = arr[(left + right) / 2];
        int l = left;
        int r = right;

        while (l <= r) {
            // 因为left+pivot要满足大于pivot+left,然后和右边的交换,这样子小的才能在左边
            while ((arr[l] + pivot).compareTo(pivot + arr[l]) < 0) {
                l++;
            }
            // 因为right+pivot要满足小于pivot+right,然后和左边的交换,这样子大的才能在右边
            while ((arr[r] + pivot).compareTo(pivot + arr[r]) > 0) {
                r--;
            }
            // 这一步进行交换,就是将大的移到右边,小的移到左边
            if (l <= r) {
                String temp = arr[l];
                arr[l] = arr[r];
                arr[r] = temp;
                l++;
                r--;
            }
        }

        // 递归左边
        if (r > left) {
            quickSork(arr, left, r);
        }
        // 递归右边
        if (l < right) {
            quickSork(arr, l, right);
        }
    }
}

复杂度分析

  • 时间复杂度:\(O(NlogN)\)
  • 空间复杂度:\(O(N)\)

思路3

  • 和思路2一样,也是使用快速排序,只是快速排序实现的方法不一样

代码

class Solution {
    public String minNumber(int[] nums) {
        int length = nums.length;

        // 将整数数组转化成字符串数组
        String[] str = new String[length];
        for (int i = 0; i < length; i++) {
            str[i] = String.valueOf(nums[i]);
        }

        // 快速排序
        quickSork(str, 0, length-1);

        // 将字符串数组里的按顺序拼接
        StringBuilder sb = new StringBuilder();
        for (String s : str) {
            sb.append(s);
        }

        return sb.toString();
    }

    public void quickSork(String[] arr, int left, int right) {
        if (left < right) {
            int l = left;
            int r = right;
            String pivot = arr[l];
            while (l < r) {
                // 因为升序,所以right要大于pivot
                while (l < r && (arr[r] + pivot).compareTo(pivot + arr[r]) >= 0) {
                    r--;
                }
                arr[l] = arr[r];
                // 因为升序,所以left要小于于pivot
                while (l < r && (arr[l] + pivot).compareTo(pivot + arr[l]) <= 0) {
                    l++;
                }
                arr[r] = arr[l];
            }
            arr[l] = pivot;
            quickSork(arr, left, l-1);
            quickSork(arr, l+1, right);
        }
    }
}

复杂度分析

  • 时间复杂度:\(O(NlogN)\)
  • 空间复杂度:\(O(N)\)
10-24 09:42