在做 Largest Number 这道题之前,我对 sort 方法的用法是非常自信的。我很清楚不传比较因子的排序会根据元素字典序(字符串的UNICODE码位点)来排,如果要根据大小排序,需要传入一个比较函数。

先来看这道题,给你一个数组,让你把数组元素拼接起来,求能拼得的最大的数。如果只有两个数字 a 和 b,如何拼?很明显比较 abba 两个数的大小,所以这道题首先需要对数组做一次排序。刷刷写下如下代码:

nums.sort(function(a, b) {
  return (b + '' + a) > (a + '' + b);
});

因为 baab 位数相同,我觉得根据字典序即可比较大小,提交,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)的更多相关文章

  1. leetcode 179. Largest Number 、剑指offer33 把数组排成最小的数

    这两个题几乎是一样的,只是leetcode的题是排成最大的数,剑指的题是排成最小的 179. Largest Number a.需要将数组的数转换成字符串,然后再根据大小排序,这里使用to_strin ...

  2. [LeetCode] 179. Largest Number 最大组合数

    Given a list of non negative integers, arrange them such that they form the largest number. Example ...

  3. [leetcode]179. Largest Number最大数

    Given a list of non negative integers, arrange them such that they form the largest number. Input: [ ...

  4. Java 特定规则排序-LeetCode 179 Largest Number

    Given a list of non negative integers, arrange them such that they form the largest number. For exam ...

  5. leetcode 179. Largest Number 求最大组合数 ---------- java

    Given a list of non negative integers, arrange them such that they form the largest number. For exam ...

  6. Java for LeetCode 179 Largest Number

    Given a list of non negative integers, arrange them such that they form the largest number. For exam ...

  7. [LeetCode] 179. Largest Number 解题思路

    Given a list of non negative integers, arrange them such that they form the largest number. For exam ...

  8. LeetCode 179 Largest Number 把数组排成最大的数

    Given a list of non negative integers, arrange them such that they form the largest number.For examp ...

  9. Leetcode 179 Largest Number 贪心

    此题主要是讲给你一组数,如何将数连在一起能得到最大值(最小值反之),注意局部最优,就是说如果 123 234两个连在一起怎么样最大,显然是234123比123234大,对于3个数我们可以找到类似的性质 ...

随机推荐

  1. Asp.net MVC Razor模板引擎技巧分享

    Razor是Asp.net MVC中新的默认模板类型, 语法简单易用.这篇文章不涉及Razor的语法,主要介绍Razor的一些在MVC项目中的使用技巧,以及脱离MVC环境下,如何使用Razor. 阅读 ...

  2. PMBOK(第五版)学习笔记二-十大知识领域(P87)

    五大项目管理过程组:启动.规划.执行.监控.收尾过程组 十大知识领域是:项目整合管理.项目范围管理.项目时间管理.项目成本管理.项目质量管理.项目人力资源管理.项目沟通管理.项目风险管理.项目采购管理 ...

  3. ORACLE AWR报告数据的导入导出实践

    关于AWR的快照数据可以导出.导入,一直没有亲手实践过.今天动手测试了一下如何导出.导入AWR数据,将AWR的数据从一测试服务器,导入到另外一台测试服务器. SQL> @?/rdbms/admi ...

  4. SQL Server(三)——增、删、改、查

    一.数据库操作 create database 数据库名称 ——创建drop database 数据库名称 ——删除use 数据库名称 ——使用go 两条SQL语句之间分隔 二.表的操作 create ...

  5. 小议如何使用APPLY

    简介 如果你打算为在结果集中的每条记录写一个调用表值函数或者表值表达式的select语句,那么你就能用到APPLY 操作符来实现.一般又两种形式写法: 第一种格式就是CROSS APPLY.这种格式可 ...

  6. mysql多实例的配置和管理

    原文地址:mysql多实例的配置和管理 作者:飞鸿无痕 多实例mysql的安装和管理 mysql的多实例有两种方式可以实现,两种方式各有利弊.第一种是使用多个配置文件启动不同的进程来实现多实例,这种方 ...

  7. DateTime的精度小问题

    一般来说判断时间的话,用个DateTime类型就已经够用了.但是有些情况,比如下面这种 DECLARE @DT1 DATETIME DECLARE @DT2 DATETIME SELECT @DT1 ...

  8. Python基础之生成器

    1.生成器简介 首先请确信,生成器就是一种迭代器.生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环中.另外,对于生成器的特殊语法支持使得编写一个生成器比 ...

  9. Error while performing database login with the sqljdbc driver:Unable to create connection. Check your URL.

    从微软官网下载jdbc驱动包sqljdbc4,运行sqljdbc_4.0.2206.100_chs.exe,将驱动包解压到了Microsoft JDBC Driver 4.0 for SQL Serv ...

  10. Nova: 虚机的块设备总结 [Nova Instance Block Device]

    和物理机一样,虚拟机包括几个重要的部分:CPU.内存.磁盘设备.网络设备等.本文将简要总结虚机磁盘设备有关知识. 1. Nova boot CLI 中有关虚机块设备的几个参数 nova boot CL ...