题目描述
给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。
注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。
示例 1:
输入:nums = [10,2]
输出:"210"
示例 2:
输入:nums = [3,30,34,5,9]
输出:"9534330"
提示:
- 1 <= nums.length <= 100
- 0 <= nums[i] <= 109
思路
题目不长,难度也只是中等,但是陷入了长考。本来以为只比较最高位即可,优先选择最高位大的,直接贪心就可以解出答案,但是我们发现很难比较这样的情况:集合中目前有[3, 32],最高位是一样的,如果我们把3的第2位虚拟成0,这里应该优先选择32,这样的情况在[3, 32, 1]这样的情况下,确实是正确的,但是如果集合是[3, 32, 3]呢,这样的情况下,就要优先选择3了。所以,用选择最高位最大数字的算法,存在2个最高位相同,但是位数不同的数字时,就需要考虑其他数字的影响,非常难处理。
看了三叶姐的题解,挺有意思的,既然一下子不知道先选谁,就22按照先后组合后的数字大小排序,最终拼成的答案ans一定是最优解。证明过程是使用了反正法,假设存在真正不等于ans的最优解max,那么必然ans中,交换2个原石的数字,会让拼成的数大于ans,单证如果存在这样的x、y,在ans中顺序和x、y,交换它们后使得ans变大,那么当初他们就不会排序成x、y,矛盾。
Java版本代码
class Solution {
public String largestNumber(int[] nums) {
int n = nums.length;
String[] ss = new String[n];
for (int i = 0; i < n; i++) ss[i] = "" + nums[i];
Arrays.sort(ss, (a, b) -> {
String sa = a + b, sb = b + a ;
return sb.compareTo(sa);
});
StringBuilder sb = new StringBuilder();
for (String s : ss) sb.append(s);
int len = sb.length();
int k = 0;
while (k < len - 1 && sb.charAt(k) == '0') k++;
return sb.substring(k);
}
}
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 15 天,点击查看活动详情