1. 程式人生 > 實用技巧 >劍指32.把陣列排成最小的數

劍指32.把陣列排成最小的數

題目描述

輸入一個正整數陣列,把數組裡所有數字拼接起來排成一個數,列印能拼接出的所有數字中最小的一個。例如輸入陣列{3,32,321},則打印出這三個數字能排成的最小數字為321323。

思路

思路1:求陣列中所有數字的全排列,類似於“字串的排列”,然後把每個排列拼起來,求最小值。 (時間複雜度很高,n個數字有n!個排列) 思路2:自定義排序規則。本題核心 -> 「如何對字串陣列進行排序」
  • 對於數字m和n,可以拼接成mn和nm,如果mn<nm,我們定義m小於n。反之則相反。利用這個排序規則,從小排到大即可實現題目要求。
  • 拼接m和n時,要考慮到大數問題,因此將m和n拼接起來的數字轉換成字串處理。因為mn和nm的字串位數相同,因此它們的大小隻需要按照字串大小的比較規則就可以了。
  • 具體實現:重寫compare(Object o1, Object o2)方法來規定比較規則。

解法1(利用Arrays.sort())

import java.util.*;

public class Solution {
    // 利用Arrays.sort()排序
    //執行時間:135ms  佔用記憶體:14720k
    public String PrintMinNumber(int [] numbers) {
        if (numbers == null || numbers.length <= 0)
            return "";
        
//Step01 int型別陣列轉化為 String型別的陣列 String[] arr = new String[numbers.length]; for (int i = 0; i < numbers.length; i++) { arr[i] = String.valueOf(numbers[i]); //arr[i] = numbers[i] + ""; // 與String相加 也可以把int轉化為String } //Step02關鍵: 對String型別陣列排序
// 使用lamda表示式Arrays.sort(arr, (引數列表) -> {返回語句}); Arrays.sort(arr, (o1, o2) -> { return (o1 + o2).compareTo(o2 + o1); //升序 兩個字串拼接,把拼接的結果較小的排到前面 }); // Arrays.sort(arr, new Comparator<String>() { // @Override // public int compare(String o1, String o2) { // return (o1 + o2).compareTo(o2 + o1); //升序 兩個字串拼接,把拼接的結果較小的排到前面 // } // }); //Step3 String[]陣列 轉化為 String型別 StringBuilder sb = new StringBuilder(); for (String s : arr){ sb.append(s); } return sb.toString(); } }

解法2(利用list.sort() 或 Collections.sort())

import java.util.*;

public class Solution {
    // 利用list.sort() 或 Collections.sort()
    // list.sort() 執行時間:93ms 佔用記憶體:15188k
    // Collections.sort() 執行時間:87ms 佔用記憶體:15148k
    public String PrintMinNumber(int [] numbers) {
        if (numbers == null || numbers.length <= 0)
            return "";
        ArrayList<String> list = new ArrayList<>();
        for (int num : numbers)
            list.add(String.valueOf(num));
//        Collections.sort(list,(o1, o2) -> {
//            return (o1+o2).compareTo(o2+o1);
//        });
        list.sort((o1, o2) -> {
            return (o1+o2).compareTo(o2+o1);
        });
        StringBuilder sb = new StringBuilder();
        for (String s : list)
            sb.append(s);
        return sb.toString();
    }
}

收穫

(1)如果把兩個int型的整數拼接起來得到的數字可能會超過int型數字能表達的範圍,導致數字溢位。 解決方案是「用字串表示數字」,這樣就能簡捷得解決大數問題了~

(2)會區分Comparable、CompareTo()、Comparator和compare()

  • Comparable是一個介面,其中可以重寫CompareTo()方法;
  • Comparator是一個比較器類:可以重寫其中compare(Object o1, Object o2)方法;Comparator物件可以被傳入Arrays.sort()、PriorityQueue()中
參考: 【Java】 劍指offer(45) 把陣列排成最小的數