問題描述:給定一個整數數組,將這個整數數組排列成一個整數,並且數組的每個元素都要用到,求所排列出的整數的範圍。
分析:這是一個很有意思的題目,初看好像是要求所有排列情況的最小值和最大值,當然這樣做也可以求出來,只不過時間複雜度過高,
另外還有一個問題是大數問題,所排列成的數可能範圍很大,超過了基本數據類型所能表示的範圍,因此需要轉換爲字符串處理。
下面詳細介紹解法:
解法一:用排列法。也就是求出這個數組的全排列,然後求出這個排列的最小值和最大值。由於排列要用到遞歸實現,
遞歸一般消耗系統大量的時間和空間,因此該方法效率略低。
解法二:直接求出排列的最大值和最小值。先介紹一種方法,對於兩個整數a和b,排列成一個整數後有兩種結果ab和ba,
這裏我們定義了一種新的大小規則,
如果ab>ba,我們就認爲a>b;
如果ab=ba,我們就認爲a=b;
如果ab<ba,我們就認爲a<b;
這不同於數學中的大小規則,爲了解決大數問題,先將整數數組轉化爲字符串數組,在進行比較。具體算法如下:
第一步:將整數數組轉換爲字符串數組。
第二步:將這個字符串數組按照我們新定義的大小規則進行排序。
第三步:將排序後的數組串連成一個字符串,這個字符串就是所要求的最小值。
第四步:將第三步字符串逆序就是所要求的最大值。
可以看出整個算法非常巧妙,避免了求排列的過程,整個算法的時間複雜度爲O(nlogn).
具體的Java代碼如下,寫法比較通用,讀者可以很容易的轉化爲其他語言實現:
public class Main {
public static String[] zuheminmax(int a[]){
String b[]=new String[a.length];
for(int i=0;i<a.length;i++) //數值轉換爲字符串
b[i]=new String(a[i]+"");
for(int i=0;i<b.length-1;i++) //按照自定義的規則排序
for(int j=i+1;j<b.length;j++)
if(compare(b[i],b[j]))
{ String t=b[i];
b[i]=b[j];
b[j]=t;
}
String minmax[]=new String[2]; //用來存儲排列數的最小值和最大值
minmax[0]=new String("");
minmax[1]=new String("");
for(int i=0;i<b.length;i++) //將所有的數連接起來,組成最小值
minmax[0]+=b[i];
for(int i=0;i<b.length;i++) //將所有的數連接起來,組成最大值
minmax[1]=b[i]+minmax[1];
return minmax;
}
public static boolean compare(String a,String b){ //自定義比較規則
String ab=a+b;
String ba=b+a;
if(ab.compareTo(ba)>0)return true;
else return false;
}
public static void main(String[] args) {
// TODO 自動生成的方法存根
int a[]={12,10,5,6,9};
String[] minmax=zuheminmax(a);
System.out.println("最小值爲:"+minmax[0]);
System.out.println("最大值爲:"+minmax[1]);
}
}
輸出結果爲:
最小值爲:1012569
最大值爲:9651210