179. 最大数 - 力扣(LeetCode)
发布:2021年9月27日20:57:12
问题描述及示例
给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。
注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例 1:
输入:nums = [10,2]
输出:“210”
示例 2:
输入:nums = [3,30,34,5,9]
输出:“9534330”
示例 3:
输入:nums = [1]
输出:“1”
示例 4:
输入:nums = [10]
输出:“10”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 109
我的题解
成功前的尝试
第一反应是先利用全排列的思想把所有可能的排列结果都给遍历出来,然后根据再从所有的可能结果中筛选出组成的值最大的那个作为答案返回即可。
/**
* @param {number[]} nums
* @return {string}
*/
var largestNumber = function(nums) {
let result = 0;
let temp = [];
backtracking(nums, []);
return result.toString();
function backtracking(nums, used) {
if(temp.length === nums.length) {
result = Math.max(result, Number(temp.join('')));
return;
}
for(let i = 0; i < nums.length; i++) {
if(used[i]) {
continue;
}
temp.push(nums[i]);
used[i] = true;
backtracking(nums, used);
used[i] = false;
temp.pop();
}
}
};
执行结果:解答错误
通过测试用例:47 / 230
输入:[999999998,999999997,999999999]
输出:"1e+27"
预期结果:"999999999999999998999999997"
时间:2021/09/27 20:59
更新:2021年10月2日17:38:49
这道题目之前做了一点,想到了这种全排列的思路,但是发现没法儿通过,后来也没想到好的点子,于是存在草稿箱里了,但是后来给忘了给补上了,今天就把这篇尘封多日的博客给补完吧。
然而,我还是太年轻了,忽视了一个重要的因素,那就是JavaScript中的数字表示范围是有局限的:
可以看到,在JavaScript中,如果整数超过了20位,那么就会用科学计数法来表示,而且也不能精确地表示原来的数,而且当把这个科学计数法表示的数字转化为字符串时也会是科学计数法。在JavaScript中,能够精确表示的最大数字就是 Number.MAX_SAFE_INTEGER
这个常数。
MAX_SAFE_INTEGER
是一个值为9007199254740991
的常量。—— JavaScript | MDN
当然,如果可以像之前做的全排列类型的题目一样在下面这个 if
判断中增添一些限制条件已达到提前“剪枝”的效果,可能可以用全排列的思路来做:
if(used[i]) {
continue;
}
但是,我想了很久都没想出来该如何增加判断条件……所以说,用全排列的思路来做还是没法儿实现效果的……于是我借助了【官方题解】。
我的题解(数组排序/Array.sort()函数)
准确来说,这个题解虽然和【官方题解】稍有不同,但确实是根据【官方题解】的思路做的变装。
总体思路也非常简单,其关键就是利用了 JavaScript 中的 Array.sort()
函数。所以在理解下面的解法之前,可以先思考一下 sort()
函数的原理:
参考:【微信公众号:高级前端进阶 2021-09-23】V8 sort是快排吗,如何实现一个 Array.prototype.sort
参考:【JavaScript】数组的sort方法排序原理详解_汪小穆的博客-CSDN博客_数组sort排序原理
整体思路抽象起来就是三步:
- 制定好
sort()
函数中的回调函数的比较规则。 - 根据上面制定好的规则,调用
sort()
函数对nums
数组进行排序。 - 把最后的排序结果拼接为一个字符串作为返回值返回。
关键就是 sort()
函数里的回调规则。这里就要利用【官方题解】中提到的提到的这种排序规则的充分必要性。具体的过程推导可以看【官方题解】中的相关描述。
简单地概括排序规则就是:假设数组中的 a
和 b
两个数字拼接之后得到的组合数字有 ab > ba
,那么就可以确定在最后的排序结果中,a
一定排在 b
的前面。
那么根据上面的排序规则,再结合 sort()
函数的原理,就可以通过比较 nums
中两两结合的数字的大小来确定最后的排序结果。而其中的“两两结合”就是关键。
下面程序中的 combination1
和 combination2
就是分别是 a
和 b
中的数字两种排序结果。然后只要根据这两种排序的大小比较结果就能判断当前的两个元素是否需要交换位置,这就是 sort()
中的回调函数的逻辑。
我写的这种回调的排序规则的实现方式和【官方题解】的不大一样,我感觉【官方题解】中的那种思路不是很直接,所以就写出了这种解法。
/**
* @param {number[]} nums
* @return {string}
*/
var largestNumber = function(nums) {
nums.sort((a, b) => {
let combination1 = a.toString() + b.toString();
let combination2 = b.toString() + a.toString();
return Number(combination2) - Number(combination1);
});
// 这里不能简单地写成return nums.join(''),而要加一个判断,详情请看下方的【补充】
return nums[0] === 0 ? '0' : nums.join('');
};
提交记录
230 / 230 个通过测试用例
状态:通过
执行用时:68 ms, 在所有 JavaScript 提交中击败了91.62%的用户
内存消耗:39.6 MB, 在所有 JavaScript 提交中击败了34.90%的用户
时间:2021/10/02 17:15
【补充】
如果这里不加上这个判断的话,那碰到 nums=[0,0]
这个用例时,就会与预期不符:
可以这么理解,如果降序排序之后,第一个元素仍为 0
(题目中已经说明了 nums
中的数字都是非负整数),那么就可以断定 nums
中的所有元素都是 0
,那么这些元素组合起来的最大数就为单位的 0
,而不是多位的 000
之类的结果。
官方题解
更新:2021年7月29日18:43:21
因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。
更新:2021年10月2日18:19:16
【更新结束】
有关参考
更新:2021年10月1日17:20:45
参考:Number.MAX_SAFE_INTEGER - JavaScript | MDN
更新:2021年10月2日17:29:57
参考:JS 因数值过大变为科学计数法,科学计数法转换为正常数值_yangzi_520的博客-CSDN博客【Array.sort() 函数的原理】
参考:【微信公众号:高级前端进阶 2021-09-23】V8 sort是快排吗,如何实现一个 Array.prototype.sort
参考:【JavaScript】数组的sort方法排序原理详解_汪小穆的博客-CSDN博客_数组sort排序原理
参考:关于js数组sort方法的实现原理总结_黯然销魂者-CSDN博客
参考:js中 sort 方法的使用 和 底层实现原理_SuperStition9的博客-CSDN博客