这样写可以把循环次数从 n 次优化到 log2(n) 次。
把 n 写成二进制形式,从低位到高位遍历,每移动一位意味着基数翻一倍,这一位为0意味着不计入结果,为1意味着计入结果。
var repeat = function (str, n) {
// 结果存放的地方
var res = '';
while (n) { // n 没到达 0 则循环
//当前位是0是1? 是 1 的话计入结果,str 是当前位的基数
if (n % 2 === 1) { res += str; }
//还有下一位吗?有的话 str 翻倍即为下一位的基数
if (n > 1) { str += str; }
//移动到下一位
n >>= 1;
}
return res
};
比如要循环字符 “abc” 11 次,11 写成二进制:1011
| | | | |
---|
二进制位 | 1 | 0 | 1 | 1 |
基数 | 8 | 4 | 2 | 1 |
基数对应字符串 | abcabcabcabcabcabcabcabc | abcabcabcabc | abcabc | abc |
基数对应字符串刚好是上一次的翻倍,这就是 if (n > 1) { str += str; }
的意思。因为 11 = 1 + 2 + 8,所以循环 11 次的字符串就等于列对应的底下的字符串相加。
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…