力扣 - 劍指 Offer 45. 把陣列排成最小的數

linzeliang發表於2021-10-24

題目

劍指 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)\)

相關文章