Given a list of non negative integers, arrange them such that they form the largest number.
For example, given [3, 30, 34, 5, 9]
, the largest formed number is 9534330
.
Note: The result may be very large, so you need to return a string instead of an integer.
Credits:
Special thanks to @ts for adding this problem and creating all test cases.
/**
* 解题思路:
*
* 思路1:
* 有一个很明显的思路,我想也是大多数人先想到的思路,
* 1.首先比较所有数的各位数字,选最大的[3, 30, 34, 5, 9],9最大,所以把它排到第一个,然后是5,排到第二个
* 2.遇到相等的数比较剩下的,3,30,34其中3都相等,比较4,0,3,也就是比较剩余的数的包含关系
* 这种思路很直观但是很难处理。
*
* 思路2:
* 3,30这两个数比较330和303,选一个大的就是330,再把34加进来34330和33034,选一个大的34330,。。。
* 依次这么下去就是最后要的答案了,是不是很简单,但是这是错误的想法,还是这组数据,咱们换个顺序
*
* 3,9比较合成93,再和30比较9330,再和34比较合成933034,再和5比较合成9330345,是不是就是错误答案。
*
* 所以不是这么简单的比较而是要进行排序
* 说到排序,7种排序中java的sort排序给了快排实现,所以直接用他就可以了,但是要根据咱们的题目把判定条件改一下
* 依据上面的思想比较两个数合成之后的大小
* 因为快排比较抽象,咱们就用最明显的冒泡排序来说明,原理是一样的
* 比如:[9,3,30,34,5]这个顺序我们做的比较相对顺序,
* 第一轮9,3合并是93和39,所以就把9放在3前面,9和30合并
* 930,309所以把9放在30前面,同理9和34比,9和5比,第一轮得到的顺序是9,3,30,34,5,
* 第二轮:3和30合并330,303所以3在30前面,3和34合并334,344所以34在3前面,34和5合并534,345所以5在34前面
* 所以第二轮找出最大的是5
* 第三轮:3和30合并330,303,3和34合并343,334,所以最大的是34
* 第四轮得到3最大
* 接下来就可以取没一轮得到的最大值就是答案了:9 5 34 3 30 ---9534330
*
* @author coder
*
*/
public class LargestNumber {
public String largestNumber(int [] num) {
int length = num.length;
if(length <= 0)
return "";
String strs[] = new String[length];
for(int i = 0; i < length; i++) {
strs[i] = String.valueOf(num[i]);
}
Arrays.sort(strs,new cmp());
String result = "" ;
for(int i = length-1 ; i >= 0; i--) {
result = result.concat(strs[i]);
}
int i = 0;
while(i < length && result.charAt(i) == '0')
i++;
if(i == length) return "0";
return result.substring(i);
}
public static void main(String[] args) {
LargestNumber largest = new LargestNumber();
int a[] = {3, 30, 34, 5, 9};
System.out.println(largest.largestNumber(a));
}
}
class cmp implements Comparator<String>{
public int compare(String a, String b) {
String ab = a.concat(b);
String ba = b.concat(a);
int i = 0;
int length = ab.length();
while(i < length) {
if(ab.charAt(i) < ba.charAt(i))
return -1;
else if(ab.charAt(i) > ba.charAt(i))
return 1;
i++;
}
return 0;
}
这个程序看着简单,其实这里面还是有很多陷阱的,比如:因为最后的数可能比较大,所以要用String类型来表示,那么在做比较方法时,就不能化成简单的Integer类型来做,需要用字符串来挨个做比较。还有就是在开头是0的判断,如果程序中就一个0,那么就要返回这个0不能再往后取值了
最后再来分析一下这个程序的复杂度空间复杂度就是O(n),时间复杂度是快排的速度加上合并的速度,所以是O(nlogn)