[ CodeWar ] - 016:数组排序

247 阅读3分钟

系列文章

题目

img-01

这题目乍一看简单的不行,然后往右边一瞟:

img-02

这么多限制条件得吗???

如果仅仅是面向 codewars 编程,还有如下的骚操作:

img-03

当然,这里还是顺着题目的意思,满足它一下吧。

解析

首先我们来看看限制:

  • 不能用临时数组
  • 0 的顺序也不能变
  • 不能用任何数组或对象的原生方法,比如 sort(), push(), map() 等等

那么这里首先想到的应该是冒泡(因为简单),这里需要做的,无非就是把前面的 0 通过冒泡排到最后,然后重新循环,遇到 0 又扔到最后去。

但如果按照上面的思路,将会有下面的坑:

连续的多个 0 将导致排序失效

input = [7, 2, 3, 0, 4, 6, 0, 0, 13, 0, 78, 0, 0, 19, 14]
output = [7,  2, 3,  4,  6, 0, 13, 78, 0, 19, 14, 0, 0,  0, 0]

至于为什么会这样,通过调试器看一下就明白了。

这里有两种思路:

  • 通过一个变量记录 0 的个数,这个数每 +1,则循环下标 -1
  • 将数组倒过来遍历

显然第二种方法要简单很多,那么我们来看看实现代码:

function removeZeros(arr{
  let len = arr.length,
    n,
    t
  for (let i = len - 1; i > -1; i--) {
    n = arr[i]
    if (parseFloat(n) === 0) {
      len--
      for (let j = i + 1; j <= len; j++) {
        t = arr[j - 1]
        arr[j - 1] = arr[j]
        arr[j] = t
      }
    }
  }
  return arr
}

优化

上述代码有什么地方可以优化呢?

  • 首先最后两位不管是不是 0,都一定是不用遍历的,所以 i 的初始值可以设置为 len - 2
  • 利用 js , 运算符
  • 利用数组完成变量交换

那么最终代码如下:

function removeZeros(arr{
  for (let len = arr.length, i = len - 2; i > -1; --i)
    if ('' + arr[i] === '0'for (let j = (--len, i + 1); j <= len; j++) arr[j - 1] = [arr[j], (arr[j] = arr[j - 1])][0]
  return arr
}