剑值offer - 把数组排成最小的数
2019-03-08 本文已影响1人
小怪兽大作战
最近又看到一道比较好的题,给大家分享一下。
题目
输入一个正整数,把数组里所有的数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如,输入数组{3,32,321},则打印出这3个数字能排成的最小数字。
思路
这道题考察字符串的处理,大数处理,排序算法
我们设计这样一种比较策略,数字a和数字b组合在一起形成两个新数字ab和ba,如果ab<ba,则我们认为a比b小。通过这样的比较策略,我们将输入数组中所有数字进行排列,将排列后的数字从前到后连接在一起,所形成的数组一定是所能排成的最小数字(证明就省略了)。
对于数字的排序,我使用了java的Collections.sort方法。该方法会检查输入待排序元素的个数,如果大于286且连续性较好就是用归并排序,如果小于47使用插入排序,其余情况使用快速排序。sort不仅可以对数字进行排序,还可以对任意元素进行排序,只需要实现一个内部类,重新compare方法就好(具体用法请看这里)。
此外,最终排成的数字可能会超过Int的最大值,这也是一个大数问题。解决大数问题我们通常使用字符串来代替数字。
代码
public class MinArray {
public String find(int[] src)throws Exception {
if(src==null||src.length==0)
throw new Exception("参数错误");
List<String> arrays=new ArrayList<String>();
for(int i=0;i<src.length;i++) {
arrays.add(String.valueOf(src[i]));
}
Collections.sort(arrays, new Comparator<String>() {
@Override
public int compare(String arg0, String arg1) {
// TODO Auto-generated method stub
return myCompare(arg0,arg1);
}
});
StringBuilder result=new StringBuilder();
for(int i=0;i<arrays.size();i++) {
result.append(arrays.get(i));
}
return result.toString();
}
private int myCompare(String a,String b) {
StringBuilder aString=new StringBuilder(a);
aString.append(b);
StringBuilder bString=new StringBuilder(b);
bString.append(a);
for(int i=0;i<aString.length();i++) {
if(aString.charAt(i)>bString.charAt(i))
return 1;
else if(aString.charAt(i)<bString.charAt(i))
return -1;
}
return 0;
}
public static void main(String[] args) {
MinArray minArray=new MinArray();
int[] src= {3,32,321};
try {
System.out.println(minArray.find(src));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}