
本文讲解如何正确排序整数数组,使其拼接后形成最大可能的数字,重点解决因整型溢出导致的 numberformatexception,并提供高效、健壮的字符串比较排序方案。
本文讲解如何正确排序整数数组,使其拼接后形成最大可能的数字,重点解决因整型溢出导致的 numberformatexception,并提供高效、健壮的字符串比较排序方案。
在解决“将数组元素重排以形成最大数值”问题时,直接按数值大小排序是错误的——例如 [111311, 1113] 中,数值上 111311 > 1113,但拼接 "1113"+"111311" = "1113111311" 明显大于 "111311"+"1113" = "1113111113"。真正决定顺序的是两个数不同拼接顺序所形成的字符串字典序大小。
原始代码中使用 Integer.parseInt(a) 将拼接字符串转为整数进行比较,会导致严重问题:
- 拼接结果(如
"111311111311")远超int范围(约 21 亿),抛出NumberFormatException; - 即使不溢出,整数比较也无法等价于字典序比较(例如
"9"vs"80":9 ,但 <code>"980" > "809")。
✅ 正确解法:全部转换为字符串,用 String.compareTo() 进行字典序比较:
public static void sortArray(int[] nums) {
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums.length; j++) {
String s1 = String.valueOf(nums[i]) + nums[j];
String s2 = String.valueOf(nums[j]) + nums[i];
if (s1.compareTo(s2) < 0) { // 注意:要升序排列使大组合在前 → 所以s1 < s2时交换,让s2(更大拼接)靠前
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}
}⚠️ 注意:上述冒泡式双循环实现逻辑需校准方向。更推荐使用 Arrays.sort() 配合自定义 Comparator,既简洁又避免手写排序的边界错误:
import java.util.*;
public class LargestNumber {
public static String largestNumber(int[] nums) {
// 转为字符串数组便于比较和拼接
String[] strs = Arrays.stream(nums)
.mapToObj(String::valueOf)
.toArray(String[]::new);
// 自定义比较器:若 a+b > b+a,则a应排在b前面
Arrays.sort(strs, (a, b) -> (b + a).compareTo(a + b));
// 边界处理:全零数组返回"0"
if ("0".equals(strs[0])) return "0";
return String.join("", strs);
}
public static void main(String[] args) {
System.out.println(largestNumber(new int[]{54, 546, 548, 60})); // 输出: "6054854654"
System.out.println(largestNumber(new int[]{111311, 1113})); // 输出: "1113111311"
}
}? 关键要点总结:
- ✅ 永远用字符串拼接 + 字典序比较(
compareTo),杜绝整型解析; - ✅ 使用
(b+a).compareTo(a+b)实现降序逻辑:确保b排在a前当且仅当b+a > a+b; - ✅ 处理全零场景:排序后若首元素为
"0",说明所有数都是0,直接返回"0"; - ⚡ 时间复杂度:
O(n log n × k),其中k是平均数字位数(字符串比较开销),远优于暴力O(n²×k); - ? 进阶优化(如答案中提及的 Map+TreeMap)适用于含大量重复元素的场景,但通用性与可读性不如标准排序方案,生产环境推荐优先使用
Arrays.sort+ Lambda。
该方法稳定、无溢出风险、语义清晰,是解决“最大数拼接”问题的标准实践。

















