刷题使我快乐,满脸开心.jpg
- 来源:力扣(LeetCode)
- 链接:https://leetcode.cn/problems/largest-number/
- 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目
给定一组非负整数 nums
,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。
注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。
示例 1:
输入:nums = [10,2]
输出:"210"
示例 2:
输入:nums = [3,30,34,5,9]
输出:"9534330"
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 109
思路
这道问题关键就在于弄明白如何比较两个数字的大小,然后去排序就完事儿了
排序
- 首先是首位不同时,那么我们其实都知道,越把大的数往前放,那么最终结果越大,所以首位不同很容易比较
- 首位相同,这里其实分两种情况
- 第一种是在后续位置上能够发现不同,比如,"456" 和 "454",那我们依然能够用不同位越大,最终越大的原则去判断
- 第二种是后续位置上没有能够发现不同,比如,"456" 和 "45","453" 和 "45",这两种情况其实还会不同,需要分情况去讨论,但是其实我们有更便捷、心智负担更小的办法,那就是把两个数字用不同的顺序
拼起来
,这样一来,拼起来
哪个数字更大,也就是说明哪个数字应该在前面!
特殊情况
最后要提一下就是小心"0"
这个特殊情况。虽然我们最终要返回的是字符串,但其实我们要返回的是拼起来之后的数字
的字符串表示,所以需要避免前缀0这类情况。
至此,也就没有太多可说的了,上代码。
代码
func largestNumber(nums []int) string {
numStrs := make([]string, 0, len(nums))
// 开始只是为了方便位比较,方便不补齐位数
// 后来看别人题解,发现还顺便规避了int溢出
for _, num := range nums {
numStrs = append(numStrs, strconv.Itoa(num))
}
sort.Slice(numStrs, func(i, j int) bool {
// 与其计算位数去补齐,不如直接拼起来看看哪个大
// 这样位数也肯定统一,不用考虑某一方溢出问题
strIJ := numStrs[i] + numStrs[j]
strJI := numStrs[j] + numStrs[i]
for k := 0; k < len(strJI); k++ {
if strIJ[k] > strJI[k] {
return true
} else if strIJ[k] < strJI[k] {
return false
}
}
return false
})
// 兼容只有0的情况,最大的都是0了,后面指定都是0,不用拼了
// 其他情况都得拼起来
if numStrs[0] == "0" {
return "0"
}
res := ""
for _, str := range numStrs {
res += str
}
return res
}