題目:輸入一個正整數數組,把數組裏面全部的數字拼接排成一個數,打印能拼接出的全部數字中的一個。例如輸入數組{3,32,321},則打印出這3個數字能排成的最小數字321323.java
這個題目最直接的作法應該是先求出這個數組中的全部數字的全排列,而後把每一個排列拼接起來,最後求出排列起來的數字的最小值。求數組的排列和麪試題28很是類似。根據排列組合的只是,n個數字總共有n!排列,咱們再來看一下更快的算法。面試
這道題其實但願咱們可以找到一個排序規則,數組根據這個規則排序以後能排成一個最小的數字。要肯定排序的規則,就要比較兩個數字,也就是給出兩個數字m和n,咱們須要肯定一個規則判斷m和n哪一個應該排在前面,而不是僅僅比較這兩個數字的值哪一個更大。算法
根據題目的要求,兩個數字m和n能拼接稱數字mn和nm。若是mn<nm,那麼咱們應該打印出mn,也就是m應該拍在N的前面,咱們定義此時m小於n;反之,若是nm<mn,咱們定義n小於m。若是mn=nm,m等於n。數組
接下來考慮怎麼去拼接數字,即給出數字m和n,怎麼獲得數字mn和nm並比較他們的大小。直接用數值去計算不難辦到,但須要考慮一個潛在的問題就是m和n都在int能表達的範圍內,把他們拼起來的數字mn和nm用int表示就有可能溢出了,因此這仍是一個隱形的大數問題。app
一個很是直觀的解決大數問題的辦法就是把數字轉換成字符串。另外,因爲把數字m和n拼接起來獲得mn和nm,他們的位數確定是相同的,所以比較它們的大小隻須要按照字符串的大小的比較規則就能夠了。ide
基於這個思路,咱們實現代碼:函數
package cglib;ui
public class jiekou {this
public void printMin(int[] arr){
int[] clone = arr.clone();
printMinNumber(clone,0,clone.length-1);
for(int i : clone)
System.out.print(i);
}
//核心+快排
public void printMinNumber(int[] arr,int left,int right){
System.out.println("left="+left);
System.out.println("right="+right);
if(left < right){
System.out.println("arr[right]="+arr[right]);
int main_number = arr[right];//321 ,n
System.out.println("main_number="+main_number);
int small_cur = left;
System.out.println("small_cur="+small_cur);
for(int j = left;j<right;j++){
System.out.println("j="+j);
System.out.println("arr[j]="+arr[j]);//3,m
if(isSmall(String.valueOf(arr[j]),String.valueOf(main_number))){
System.out.println("arr[j]小於main_number,交換arr[j]和arr[small_cur]");
int temp = arr[j];
arr[j] = arr[small_cur];
arr[small_cur] = temp;
System.out.println("small_cur="+small_cur);
small_cur++;
System.out.println("small_cur="+small_cur);
}
}
System.out.println("arr[right]="+arr[right]);
System.out.println("arr[small_cur]="+arr[small_cur]);
System.out.println("main_number="+main_number);
arr[right]= arr[small_cur];
System.out.println("交換後arr[right]="+arr[right]);
arr[small_cur] = main_number;
System.out.println("交換後arr[small_cur]="+arr[small_cur]);
System.out.println("small_cur="+small_cur);
printMinNumber(arr,0,small_cur-1);
printMinNumber(arr,small_cur+1,right);
}
}
public boolean isSmall(String m,String n){
System.out.println("進入isSmall");
System.out.println("m="+m);
System.out.println("n="+n);
String left = m+n;
String right = n+m;
System.out.println("left="+left);
System.out.println("right="+right);
System.out.println("left.length()="+left.length());
boolean result = false;
for(int i = 0;i<left.length();i++){
System.out.println("比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真");
System.out.println("i="+i);
System.out.println("left.charAt(i)="+left.charAt(i));
System.out.println("right.charAt(i)="+right.charAt(i));
if(left.charAt(i)<right.charAt(i))
return true;
else
if(left.charAt(i)>right.charAt(i))
return false;
}
return result;
}
public static void main(String[] args){
int arr[] = {3,32,321};
jiekou test = new jiekou();
test.printMin(arr);
}
} spa
輸出:
left=0
right=2
arr[right]=321
main_number=321
small_cur=0
j=0
arr[j]=3
進入isSmall
m=3
n=321
left=3321
right=3213
left.length()=4
比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真
i=0
left.charAt(i)=3
right.charAt(i)=3
比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真
i=1
left.charAt(i)=3
right.charAt(i)=2
j=1
arr[j]=32
進入isSmall
m=32
n=321
left=32321
right=32132
left.length()=5
比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真
i=0
left.charAt(i)=3
right.charAt(i)=3
比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真
i=1
left.charAt(i)=2
right.charAt(i)=2
比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真
i=2
left.charAt(i)=3
right.charAt(i)=1
arr[right]=321
arr[small_cur]=3
main_number=321
交換後arr[right]=3
交換後arr[small_cur]=321
small_cur=0
left=0
right=-1
left=1
right=2
arr[right]=3
main_number=3
small_cur=1
j=1
arr[j]=32
進入isSmall
m=32
n=3
left=323
right=332
left.length()=3
比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真
i=0
left.charAt(i)=3
right.charAt(i)=3
比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真
i=1
left.charAt(i)=2
right.charAt(i)=3
arr[j]小於main_number,交換arr[j]和arr[small_cur]
small_cur=1
small_cur=2
arr[right]=3
arr[small_cur]=3
main_number=3
交換後arr[right]=3
交換後arr[small_cur]=3
small_cur=2
left=0
right=1
arr[right]=32
main_number=32
small_cur=0
j=0
arr[j]=321
進入isSmall
m=321
n=32
left=32132
right=32321
left.length()=5
比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真
i=0
left.charAt(i)=3
right.charAt(i)=3
比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真
i=1
left.charAt(i)=2
right.charAt(i)=2
比較m和n組成的數的每一個子數的大小,若是mn<nm,則返回真
i=2
left.charAt(i)=1
right.charAt(i)=3
arr[j]小於main_number,交換arr[j]和arr[small_cur]
small_cur=0
small_cur=1
arr[right]=32
arr[small_cur]=32
main_number=32
交換後arr[right]=32
交換後arr[small_cur]=32
small_cur=1
left=0
right=0
left=2
right=1
left=3
right=2
321323
或者:
package cglib;
import java.util.Arrays;
public class jiekou {
public static void main(String ss[]) {
MString s[] = new MString[3];
s[0] = new MString();
s[0].src = "3";
s[1] = new MString();
s[1].src = "32";
s[2] = new MString();
s[2].src = "321";
function(s);
for (int i = 0; i < s.length; i++) {
System.out.print(s[i].src);
}
}
public static void function(MString s[]) {
Arrays.sort(s);
}
}
class MString implements Comparable<MString> {
@Override
public String toString() {
return "MString [src=" + src + "]";
}
String src;
@Override
public int compareTo(MString paramT) {
System.out.println("this.src="+this.src);
System.out.println("paramT.src="+paramT.src);
String s1 = this.src + paramT.src;
System.out.println("s1="+s1);
String s2 = paramT.src + this.src;
System.out.println("s2="+s2);
if (s1.compareTo(s2) == 0) {
return 0;
} else if (s1.compareTo(s2) > 0) {
return 1;
} else
return -1;
}
}
MString用來存儲要比較的字符串,實現了compare函數,用來比較。
compare函數的意思是若是組成的數字mn>nm,那麼就返回nm,不然返回mn。
---------------------------------
下面說一下Comparable接口。
實現該接口的話,須要實現comparaTo函數。這個函數是用於兩個對象作比較的。若是相等則返回0,大則返回1,小則返回-1。
在上面的代碼中,咱們實現了Comparable接口而且在實現的函數中作了兩個字符串的比較。
實現了Comparable接口的全部類均可以使用comparaTo函數來比較大小。
輸出:
this.src=32
paramT.src=3
s1=323
s2=332
this.src=321
paramT.src=32
s1=32132
s2=32321
321323
或者
import java.util.Arrays;
import java.util.Comparator;
public class jiekou {
public static void main(String ss[]) { //int s[] = new int[3]; int s[] = {3,32,321}; jiekou test = new jiekou(); System.out.print(test.PrintMinNumber(s)); } public String PrintMinNumber(int [] numbers) { String[] s = new String[numbers.length]; for (int i = 0; i < s.length; i++) s[i] = String.valueOf(numbers[i]); Arrays.sort(s, 0, s.length, new Comparator<String>() { @Override public int compare(String o1, String o2) { return (o1+o2).compareTo(o2+o1); } }); StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length; i++) sb.append(s[i]); return sb.toString(); } }