题目:输入一个正整数数组,把数组里面全部的数字拼接排成一个数,打印能拼接出的全部数字中的一个。例如输入数组{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(); } }