【Daily Interview】- 27 left-pad

396 阅读2分钟

题目

img01

分析

这个题目很简单,不过在开源社区其实有着相当的知名度,因为一个开发者对 NPM 公司不满,unpublish 了自己的所有模块。其中包括被广泛使用的 left-pad,导致 Babel、ReactNative、Ember 等大量工具构建失败。

思路很简单,直接在左边进行补齐即可:

const leftpad = (str, c, len) => {
  if (!c && c !== 0) c = " ";
  len = len - str.length;
  return c + Array(len).join(c) + str;
};

而 Babel 官方的代码也和上述代码大致相似:

img02

不过这段代码遭到了大佬左耳朵耗子的吐槽,而他也给出了自己的思路:二分法。

第一种思路显然算法的时间复杂度为 On,假设需要在字符串前面拼接 20 个 0,那么就需要拼接 20 次。

但如果每次将结果给存起来,那么我们会得到如下的缓存:

1 0
2 00
3 0000
4 00000000

这时,填充到 20 则只需要两个编号为 4 的字符串和一个编号为 3 的字符串即可,效率远远优于直接循环,其时间复杂度为 Olog2n。

对于使用二分法来解决这个问题,我们需要注意的是:

  • 当 len 为 1 的时候直接返回 left + str
  • 当 len 为奇数的时候将 c + left 的值给 left

💡 其实反推一下就可以得出上述结论,当需要补齐的长度为 1 的时候,直接返回 0 + str 即可,这时 left 就是 0。当 c 为 3 的时候。需要返回的是 0 + 00 + str,此时 left 是 0,c 是 00,以此类推。

代码如下:

const leftpad = (str, c, len) => {
  len = len - str.length;
  c = String(c);
  let total = "";
  while (len) {
    if (len % 2 === 1) {
      total += c;
    }
    if (len === 1) {
      return total + str;
    }
    c += c;
    len = parseInt(len / 2);
  }
};