题目:输入一个正整数数组。把数组里面全部的数字拼接排成一个数,打印能拼接出的全部数字中的一个。比如输入数组{3,32。321}。则打印出这3个数字能排成的最小数字321323.
这个题目最直接的做法应该是先求出这个数组中的全部数字的全排列,然后把每一个排列拼接起来,最后求出排列起来的数字的最小值。
求数组的排列和面试题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表示就有可能溢出了,所以这还是一个隐形的大数问题。
一个很直观的解决大数问题的办法就是把数字转换成字符串。
另外,因为把数字m和n拼接起来得到mn和nm,他们的位数肯定是同样的,因此比較它们的大小仅仅须要依照字符串的大小的比較规则就能够了。
基于这个思路。我们实现代码:
/** * 把数组排成最小的数 * 输入一个正整数数组,把数组里全部的数字拼接起来排成一个数。 * 打印能拼接出来的全部数字中最小的一个 */package swordForOffer;/** * @author JInShuangQi * * 2015年8月9日 */public class E33SortArrayForMinNumber { 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){ if(left < right){ int main_number = arr[right]; int small_cur = left; for(int j = left;jright.charAt(i)) return false; } return result; } public static void main(String[] args){ int arr[] = {3,32,321}; E33SortArrayForMinNumber test = new E33SortArrayForMinNumber(); test.printMin(arr); }}