题目
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);
}
};