JavaScript中sort方法的一个坑(leetcode 179. Largest Number)
在做 Largest Number 这道题之前,我对 sort 方法的用法是非常自信的。我很清楚不传比较因子的排序会根据元素字典序(字符串的UNICODE码位点)来排,如果要根据大小排序,需要传入一个比较函数。
先来看这道题,给你一个数组,让你把数组元素拼接起来,求能拼得的最大的数。如果只有两个数字 a 和 b,如何拼?很明显比较 ab 和 ba 两个数的大小,所以这道题首先需要对数组做一次排序。刷刷写下如下代码:
nums.sort(function(a, b) {
return (b + '' + a) > (a + '' + b);
});
因为 ba 和 ab 位数相同,我觉得根据字典序即可比较大小,提交,221 组数据跪在了 201 组。我开始怀疑算法的正确性,直到无意中把比较函数改了下,便 AC 了:
nums.sort(function(a, b) {
return (b + '' + a) - (a + '' + b);
});
这真的有区别么?印象中 c++ 中调用 STL 的 sort 函数,在比较函数中一直用的 < 以及 > 啊。我承认我以前从没有留意过。
我们把问题简化,先来看以下代码:
var largestNumber = function(nums) {
nums.sort(function(a, b) {
return a - b;
});
return nums;
};
console.log(largestNumber([41,32,81,97,99,91,90,63,76,76,67]));
// [32, 41, 63, 67, 76, 76, 81, 90, 91, 97, 99]
这是一次升序排序,结果完美,那么,为什么能得到这样的结果,有思考过 return a - b 的意思么?
如果指明了 compareFunction ,那么数组会按照调用该函数的返回值排序。记 a 和 b 是两个将要被比较的元素:
- 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
- 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。
- 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
上面的的代码其实可以扩写成这样:
var largestNumber = function(nums) {
nums.sort(function(a, b) {
if (a - b > 0)
return 1; // a 比 b 大,b 排到 a 前
else if (a - b < 0)
return -1; // a 比 b 小,a 排到 b 前
else
return 0; // a 和 b 一样大,a 和 b 相对位置不变
});
return nums;
};
仔细想想,这样便是一个升序排列。
再来看错误写法:
var largestNumber = function(nums) {
nums.sort(function(a, b) {
return a > b;
});
return nums;
};
console.log(largestNumber([41,32,81,97,99,91,90,63,76,76,67]));
// [91, 41, 32, 63, 67, 76, 76, 81, 90, 97, 99]
其实可以扩写为:
var largestNumber = function(nums) {
nums.sort(function(a, b) {
if (a > b)
return 1; // true 隐式转换为 1; b 排到 a 前
else
return 0; // false 隐式转换为 0; 相对位置不变
});
return nums;
};
仔细想想,明显有问题。a > b 时 b 排到 a 前没有问题,a < b 时位置不变,这就不对了。如果 a < b 时 return -1,让 a 排到 b 前,就对了。所以这样写也是没问题的:
var largestNumber = function(nums) {
nums.sort(function(a, b) {
if (a > b)
return 1;
else
return -1;
});
return nums;
};
当然,a === b 这个条件可以随意归到 a > b 或者 a < b 那,也可以拎出来独立,以上代码我是归到 a < b 那了。
另外还需要注意的一点是,比较函数中的 a 和 b 参数,在数组中的位置是任意的,并不是 a 前 b 后。这里我写了段测试代码:
var largestNumber = function(nums) {
nums.sort(function(a, b) {
console.log(a, b);
console.log(nums.concat());
return a - b;
});
return nums;
};
console.log(largestNumber([41,32,81,97,99,91,90,63,76,76,67]));
结果很明显:

最后勉强回忆起 C++ 中的 sort 的比较函数返回的是一个 bool 值,而 JavaScript 比较函数能返回三个值,跟 C++ 中的 qsort 类似?实在回忆不起来也不想回忆了。
本题完整代码可以移步 https://github.com/hanzichi/leetcode/tree/master/Algorithms/Largest%20Number。PS:还有一个坑,拼起来的字符串需要去前导 0。
JavaScript中sort方法的一个坑(leetcode 179. Largest Number)的更多相关文章
- leetcode 179. Largest Number 、剑指offer33 把数组排成最小的数
这两个题几乎是一样的,只是leetcode的题是排成最大的数,剑指的题是排成最小的 179. Largest Number a.需要将数组的数转换成字符串,然后再根据大小排序,这里使用to_strin ...
- [LeetCode] 179. Largest Number 最大组合数
Given a list of non negative integers, arrange them such that they form the largest number. Example ...
- [leetcode]179. Largest Number最大数
Given a list of non negative integers, arrange them such that they form the largest number. Input: [ ...
- Java 特定规则排序-LeetCode 179 Largest Number
Given a list of non negative integers, arrange them such that they form the largest number. For exam ...
- leetcode 179. Largest Number 求最大组合数 ---------- java
Given a list of non negative integers, arrange them such that they form the largest number. For exam ...
- Java for LeetCode 179 Largest Number
Given a list of non negative integers, arrange them such that they form the largest number. For exam ...
- [LeetCode] 179. Largest Number 解题思路
Given a list of non negative integers, arrange them such that they form the largest number. For exam ...
- LeetCode 179 Largest Number 把数组排成最大的数
Given a list of non negative integers, arrange them such that they form the largest number.For examp ...
- Leetcode 179 Largest Number 贪心
此题主要是讲给你一组数,如何将数连在一起能得到最大值(最小值反之),注意局部最优,就是说如果 123 234两个连在一起怎么样最大,显然是234123比123234大,对于3个数我们可以找到类似的性质 ...
随机推荐
- U-BLOX GPS 模块及GPRMC指令解析
受朋友所托,调试一款GPS模块,该模块是UBLOX的NEO-6M GPS模组.想到用这款GPS的人较多,自己日后也有可能在用到这个模块,就写下这份笔记. 1. 介绍 基本信息如下: 1, 模块采用U- ...
- WebApi深入学习--特性路由
特性路由 WebApi2默认的路由规则我们称作基于约定路由,很多时候我们使用RESTful风格的URI.简单的路由是没问题的,如 api/Products/{id},但有些事很难处理的,如资源之间存在 ...
- A record--Offline deployment of Big Data Platform CDH Cluster
A record--Offline deployment of Big Data Platform CDH Cluster Tags: Cloudera-Manager CDH Hadoop Depl ...
- 用VC6开发嵌入式LINUX程序
黄山松 (Tom Huang) 发表于博客园http://www.cnblogs.com/tomview/ 首先说明一下,VC6自然不能直接开发LINUX程序,主要使用的是它的编辑环境而已,但是作为一 ...
- linux添加开机自启动脚本示例详解
linux下(以RedHat为范本)添加开机自启动脚本有两种方法,先来简单的; 一.在/etc/rc.local中添加如果不想将脚本粘来粘去,或创建链接什么的,则:step1. 先修改好脚本,使其所有 ...
- andriod fragment调用Activity函数方法
(1)新增一个activity public MainActivity getMainActivity(); } (2)在MainActivity 的Java文件中增加 getMainActivit公 ...
- jquery 获取设置值、添加元素详解
jQuery 获取内容和属性 jQuery DOM 操作 jQuery 中非常重要的部分,就是操作 DOM 的能力. jQuery 提供一系列与 DOM 相关的方法,这使访问和操作元素和属性变得很容易 ...
- Neutron VxLAN + Linux Bridge 环境中的网络 MTU
1. 基础知识 1.1 MTU 一个网络接口的 MTU 是它一次所能传输的最大数据块的大小.任何超过MTU的数据块都会在传输前分成小的传输单元.MTU 有两个测量层次:网络层和链路层.比如,网络层 ...
- [书目20160526]Brain Rules 让大脑自由:释放天赋的12条定律
推荐序1 12条定律,让大脑更聪明推荐序2 走过迷雾地带前 言 人人都有一个不可思议的大脑 定律1:越运动,大脑越聪明 信不信,“驴友”比“沙发土豆”更聪明! 老板,请把办公室的咖啡机换成跑步机! ...
- BZOJ1216[HNOI2003]操作系统 [模拟 优选队列]
1216: [HNOI2003]操作系统 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 754 Solved: 421[Submit][Status ...