这是我的挑战:
给出一个非负整数列表,以这样的方式排列它们,使它们形成尽可能小的数字。
结果会非常大,因此会以字符串的形式返回结果。
如果我将输入数组视为{20,1,5},则所有排列如下:
2015,2051,1205,1520,5201,5120但由于1205最小,因此应该是结果。
输入数组{20,1,5}
结果:1205
以下是方法签名:
private String getSmallestNumber(Integer[] nums) {
}
我应该使用什么算法?
提出类似问题:
http://www.practice.geeksforgeeks.org/problem-page.php?pid=380
答案 0 :(得分:3)
我完成了我的代码,但请建议我更好的算法
private String getSmallestNumber(Integer[] nums) {
String[] arr = new String[nums.length];
for (int i = 0; i < nums.length; i++) {
arr[i] = String.valueOf(nums[i]);
}
Arrays.sort(arr, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return (a + b).compareTo(b + a);
}
});
StringBuilder sb = new StringBuilder();
for (String s : arr) {
sb.append(s);
}
while (sb.charAt(0) == '0' && sb.length() > 1) {
sb.deleteCharAt(0);
}
return sb.toString();
}
答案 1 :(得分:1)
解决方案是使用自定义比较器对数组进行排序,该比较器逐位进行比较。换句话说,给定两个数字,将第一个数字的最高有效位数与第二个数字的最高有效位数进行比较。然后比较第二个数字,依此类推,直到到达其中一个数字的末尾,或者数字不相等。数字较低的数字在答案中排在第一位。
例如20来自5之前因为2小于5. 1000来自99因为1小于9. 123789来自1239之前因为7小于9.
所以诀窍是通过乘以10来缩小较小的数字,直到两个数字具有相同的位数。例如,给出一个六位数字和一个四位数字,如
123789
1239
您需要将四位数字乘以100,这样两个数字的位数相同
123789
123900
然后一个简单的整数比较告诉你123789在1239之前出现。所以比较器的代码看起来像这样
int compare( int a, int b )
{
int special = b - a; // special case, e.g. 123 and 123000
if ( a <= b ) {
for ( int n = 1; n <= b; n *= 10 )
if ( n > a )
a *= 10;
} else {
for ( int n = 1; n <= a; n *= 10 )
if ( n > b )
b *= 10;
}
if ( a == b )
return special;
else
return a - b;
}
有一种特殊情况,两个数字在缩放后最终相等。例如,给定数字123000和123,正确的顺序是在123之前放置123000,因为这将三个零放在数组中,即123000123优于123123000.因此需要特殊情况来选择如果数字在缩放后相等,则首先是数字。因此,需要变量名为special
。