位运算题目:连接连续二进制数字
文章目录
- 题目
- 标题和出处
- 难度
- 题目描述
- 要求
- 示例
- 数据范围
- 解法
- 思路和算法
- 代码
- 复杂度分析
题目
标题和出处
标题:连接连续二进制数字
出处:1680. 连接连续二进制数字
难度
5 级
题目描述
要求
给定一个整数 n \texttt{n} n,将 1 \texttt{1} 1 到 n \texttt{n} n 的二进制表示连接得到一个二进制数,返回连接得到的二进制数对应的十进制数对 10 9 + 7 \texttt{10}^\texttt{9} + \texttt{7} 109+7 取余的结果。
示例
示例 1:
输入:
n
=
1
\texttt{n = 1}
n = 1
输出:
1
\texttt{1}
1
解释:二进制的
"1"
\texttt{"1"}
"1" 对应十进制的
1
\texttt{1}
1。
示例 2:
输入:
n
=
3
\texttt{n = 3}
n = 3
输出:
27
\texttt{27}
27
解释:二进制下,
1
\texttt{1}
1、
2
\texttt{2}
2 和
3
\texttt{3}
3 分别对应
"1"
\texttt{"1"}
"1"、
"10"
\texttt{"10"}
"10" 和
"11"
\texttt{"11"}
"11"。
将它们依次连接,得到
"11011"
\texttt{"11011"}
"11011",对应十进制的
27
\texttt{27}
27。
示例 3:
输入:
n
=
12
\texttt{n = 12}
n = 12
输出:
505379714
\texttt{505379714}
505379714
解释:连接结果为
"1101110010111011110001001101010111100"
\texttt{"1101110010111011110001001101010111100"}
"1101110010111011110001001101010111100",对应十进制的
118505380540
\texttt{118505380540}
118505380540。
对
10
9
+
7
\texttt{10}^\texttt{9} + \texttt{7}
109+7 取余后,结果为
505379714
\texttt{505379714}
505379714。
数据范围
- 1 ≤ n ≤ 10 5 \texttt{1} \le \texttt{n} \le \texttt{10}^\texttt{5} 1≤n≤105
解法
思路和算法
由于 1 1 1 到 n n n 的二进制表示的连接结果可能很长,因此需要在遍历连接结果的过程中计算结果。
初始时,连接结果是 0 0 0。当遍历到整数 i i i 时,假设 1 1 1 到 i − 1 i - 1 i−1 的连接结果对应的整数是 x x x,整数 i i i 的二进制表示有 bits \textit{bits} bits 位,则 1 1 1 到 i − 1 i - 1 i−1 的连接结果对应的整数是将 x x x 左移 bits \textit{bits} bits 位之后加 i i i。因此,只要知道 1 1 1 到 n n n 的每个整数的二进制表示的位数,即可得到连接的结果对应的整数。
如果正整数 x x x 是 2 2 2 的整数次幂,则 x x x 的二进制表示的位数比 x − 1 x - 1 x−1 的二进制表示的位数多 1 1 1,这里规定 0 0 0 的二进制表示的位数是 0 0 0。正整数 x x x 是 2 2 2 的整数次幂等价于 x & ( x − 1 ) = 0 x ~\&~ (x - 1) = 0 x & (x−1)=0,因此可以在 O ( 1 ) O(1) O(1) 的时间内判断一个整数是不是 2 2 2 的整数次幂。
由此可以得到如下解法。
用 num \textit{num} num 表示连接结果,用 bits \textit{bits} bits 表示当前整数的二进制表示的位数,初始时 num \textit{num} num 和 bits \textit{bits} bits 都是 0 0 0。依次遍历从 1 1 1 到 n n n 的每个整数,对于整数 i i i,执行如下操作。
-
判断 i i i 是否是 2 2 2 的整数次幂。如果 i & ( i − 1 ) = 0 i ~\&~ (i - 1) = 0 i & (i−1)=0,则 i i i 是 2 2 2 的整数次幂,将 bits \textit{bits} bits 加 1 1 1,否则 bits \textit{bits} bits 不变。此时 bits \textit{bits} bits 是 i i i 的二进制表示的位数。
-
将 num \textit{num} num 的值更新为 ( num < < bits ) + i (\textit{num} << \textit{bits}) + i (num<<bits)+i,并将更新后的值对 1 0 9 + 7 10^9 + 7 109+7 取余。
遍历结束之后, num \textit{num} num 即为 1 1 1 到 n n n 的二进制表示的连接结果对应的整数。
需要注意的是,由于 n n n 的最大值是 1 0 5 10^5 105,因此 bits \textit{bits} bits 的最大值是 17 17 17, nums < < bits \textit{nums} << \textit{bits} nums<<bits 的结果可能超出 32 32 32 位整数的范围。为了避免溢出,应将 num \textit{num} num 声明为 long \texttt{long} long 型,返回结果时转成 int \texttt{int} int 型。
代码
class Solution {
public int concatenatedBinary(int n) {
final int MODULO = 1000000007;
long num = 0;
int bits = 0;
for (int i = 1; i <= n; i++) {
if ((i & (i - 1)) == 0) {
bits++;
}
num = ((num << bits) + i) % MODULO;
}
return (int) num;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是给定的整数。需要遍历 n n n 个整数,每个整数的操作时间都是 O ( 1 ) O(1) O(1)。
-
空间复杂度: O ( 1 ) O(1) O(1)。