#179
中等
低频
贪心算法最大数
这是一道围绕字符串展开的高频练习。建议先掌握「贪心算法」这套写法,再结合下方步骤讲解理解状态维护、边界处理和复杂度取舍。
字符串
题目分析
这道题表面上是在处理「最大数」,但先要想清楚题目到底让你返回什么,以及过程中哪些约束必须一直满足。从题型上看,它主要在考 字符串 这些能力。这类题的关键不是“贪心”两个字,而是能不能说明每一步的局部选择为什么不会破坏最终答案。只有先把题目要求翻译成人话,后面的推荐代码才是在实现思路,而不是直接给答案。
接下来怎么看推荐代码: 带着这个理解再看推荐代码时,重点观察这条主线:把数字转成字符串后按
a+b 和 b+a 的大小排序,再顺序拼接。推荐代码
推荐解法:贪心算法
时间复杂度: O(n log n)
空间复杂度: O(n)
核心思路: 把数字转成字符串后按
a+b 和 b+a 的大小排序,再顺序拼接。import java.util.Arrays;
import java.util.Comparator;
class Solution {
public String largestNumber(int[] nums) {
// 将每个数字转换为字符串
String[] strs = new String[nums.length];
for (int i = 0; i < nums.length; i++) {
strs[i] = String.valueOf(nums[i]);
}
// 使用自定义比较器排序
// 比较规则:如果 x + y > y + x,则 x 应该排在 y 前面
Arrays.sort(strs, new Comparator<String>() {
@Override
public int compare(String x, String y) {
return (y + x).compareTo(x + y);
}
});
// 处理所有数字都是0的情况
if (strs[0].equals("0")) {
return "0";
}
// 连接所有字符串
StringBuilder res = new StringBuilder();
for (String s : strs) {
res.append(s);
}
return res.toString();
}
}结构化讲解
面试时怎么讲
开场思路
这题我会用贪心排序,关键比较规则是看两个数字谁放前面更优。
核心过程
- 先把所有数字转成字符串。
- 定义比较器:若
a+b更大,就让a排前面。 - 按这个规则排序后顺序拼接。
- 最后处理全零的特殊情况。
复杂度总结
时间复杂度 O(n log n),空间复杂度 O(n)。
面试补一句:这题最值钱的一句解释,是“比较的是拼接结果,不是原数大小”。
核心思路
最大数的关键不是数值大小,而是拼接顺序。两个数字谁该排前面,取决于 ab 和 ba 哪个更大。
步骤讲解
1
先把数字转成字符串
后续比较的对象不是数值本身,而是字符串拼接结果。
为什么这样做:题目目标是最大拼接串,不是数值排序。
对应代码提示:String[] arr = ...;
2
按拼接结果定义排序规则
若 a+b 大于 b+a,则 a 应排在 b 前面。
为什么这样做:这是决定全局最优拼接顺序的局部比较准则。
对应代码提示:Arrays.sort(arr, (a, b) -> (b + a).compareTo(a + b));
3
拼接后处理全零情况
若排序后第一个字符串是 0,说明所有数字都是 0,直接返回 0。
为什么这样做:否则会得到像
0000 这样的冗余结果。对应代码提示:if (arr[0].equals("0")) return "0";
易错点
按数值大小排序
会在 3 和 30 这类例子上失败。
正确理解:比较标准必须是拼接结果,不是单个数值。
没处理全零结果
会输出多个前导零。
正确理解:排序后若首元素为
0,直接返回单个 0。担心自定义排序不传递
这个比较规则是题目标准做法,可稳定得到正确顺序。
正确理解:面试里直接基于
a+b 与 b+a 解释即可。复杂度与适用判断
时间复杂度:O(n log n)
空间复杂度:O(n)
比其他方案更好在哪里:比暴力枚举所有排列高效得多。
适用判断:字符串拼接最值问题若能定义两两局部优先级,优先考虑贪心排序。
额外提醒
ab和ba的比较,是整题唯一关键。
动画演示
如果你还没完全看懂,可以展开动画演示。
贪心算法动画演示
想看这段解法是怎么一步步运行的,可以展开动画继续观察。
贪心算法动画演示
想看这段解法是怎么一步步运行的,可以展开动画继续观察。
准备就绪 - 输入数字数组(用逗号分隔),然后点击开始
动画演示仅在桌面端提供,移动端请优先阅读推荐代码与结构化讲解。