5620.连续连接的二进制数字
第一次 JS 双百,虽然是虚假的双百 😭
写法1 :耿直模拟
使用 JS 中的进制转换函数 toString
和 parseInt
实现模拟。
toString
能将十进制数字转换为任意进制数字,如 (5).toString(2) = 101
parseInt
能将二进制数字转换为十进制数字,如 parseInt('101', 2) = 5
不过这种写法效率可能有点差,会超时…
var concatenatedBinary = function(n) {
let mod = 1e9 + 7;
let sum = "";
for (let i = 1; i <= n; i++) {
sum += (i).toString(2); // 十进制转二进制然后字符串拼接
let t = parseInt(sum, 2); // 二进制字符串转十进制判断是否需要取余
if (t >= mod) {
t %= mod;
sum = (t).toString(2);
}
}
return parseInt(sum, 2);
};
写法2 :二进制移位模拟
其实,我们稍微列一下二进制就能够比较直观的找到连接的规律:
我们知道,对于二进制,每次向左移动一位就是乘上一个 2
,因此若当前要连接的数字的二进制位数是两位,我们每次移动就应该乘上一个 4
,三位二进制就乘上一个 8
,移动完后末尾再加上当前的数字即可。
若使用 JS ,需要使用 BigInt
类型,因为后面在进行移位的时候可能会过大导致算术溢出…
如: 28399128732189371 << 1 -> -670661256
关于 BigInt
的使用也很简单,普通数字后面加一个 n
就代表了 BigInt
类型,如 1n
,或是使用构造器 BigInt(1)
。
使用 BigInt
时需要注意的是 bigint
类型只能与 bigint
类型进行运算,且 Math
中的方法也不能应用在 bigint
类型上。
var concatenatedBinary = function(n) {
let mod = BigInt(1e9 + 7); // JS 需要使用大数,不然会溢出
let sum = 0n;
let p = 1n;
let l = 2n;
for (let i = 1n; i <= n; i++) {
if (i === l) { // 若 i 为 2 的倍数,那么移位数 + 1
p++;
l *= 2n;
}
sum <<= p; // 累加的和每次移 p 位,然后再加上当前值
sum += i;
if (sum >= mod) {
sum %= mod;
}
}
return sum;
};
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!