127 lines
2.5 KiB
Markdown
127 lines
2.5 KiB
Markdown
|
|
|||
|
## 题目地址
|
|||
|
https://leetcode.com/problems/bitwise-and-of-numbers-range/description/
|
|||
|
|
|||
|
## 题目描述
|
|||
|
|
|||
|
```
|
|||
|
Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive.
|
|||
|
|
|||
|
Example 1:
|
|||
|
|
|||
|
Input: [5,7]
|
|||
|
Output: 4
|
|||
|
Example 2:
|
|||
|
|
|||
|
Input: [0,1]
|
|||
|
Output: 0
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
## 思路
|
|||
|
|
|||
|
一个显而易见的解法是, 从m到n依次进行`求与`的操作。
|
|||
|
|
|||
|
```js
|
|||
|
|
|||
|
let res = m;
|
|||
|
for (let i = m + 1; i <= n; i++) {
|
|||
|
res = res & i;
|
|||
|
}
|
|||
|
return res;
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
但是, 如果你把这个solution提交的话,很显然不会通过, 会超时。
|
|||
|
|
|||
|
我们依旧还是用trick来简化操作。 我们利用的性质是, n个连续数字求与的时候,前m位都是1.
|
|||
|
|
|||
|
举题目给的例子:[5,7] 共 5, 6,7三个数字, 用二进制表示 101, 110,111,
|
|||
|
这三个数字特点是第一位都是1,后面几位求与一定是0.
|
|||
|
|
|||
|
再来一个明显的例子:[20, 24], 共 20, 21, 22, 23,24五个数字,二进制表示就是
|
|||
|
|
|||
|
```
|
|||
|
0001 0100
|
|||
|
0001 0101
|
|||
|
0001 0110
|
|||
|
0001 0111
|
|||
|
0001 1000
|
|||
|
```
|
|||
|
|
|||
|
这五个数字特点是第四位都是1,后面几位求与一定是0.
|
|||
|
|
|||
|
因此我们的思路就是, 求出这个数字区间的数字前多少位都是1了,那么他们求与的结果一定是前几位数字,然后后面都是0.
|
|||
|
|
|||
|
|
|||
|
## 关键点解析
|
|||
|
|
|||
|
|
|||
|
- n个连续数字求与的时候,前m位都是1
|
|||
|
|
|||
|
- 可以用递归实现, 个人认为比较难想到
|
|||
|
|
|||
|
- bit 运算
|
|||
|
|
|||
|
代码:
|
|||
|
|
|||
|
```js
|
|||
|
|
|||
|
(n > m) ? (rangeBitwiseAnd(m/2, n/2) << 1) : m;
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
> 每次问题规模缩小一半, 这是二分法吗?
|
|||
|
|
|||
|
## 代码
|
|||
|
|
|||
|
语言支持:JavaSCript,Python3
|
|||
|
|
|||
|
JavaScript Code:
|
|||
|
|
|||
|
```js
|
|||
|
/*
|
|||
|
* @lc app=leetcode id=201 lang=javascript
|
|||
|
*
|
|||
|
* [201] Bitwise AND of Numbers Range
|
|||
|
*
|
|||
|
*/
|
|||
|
/**
|
|||
|
* @param {number} m
|
|||
|
* @param {number} n
|
|||
|
* @return {number}
|
|||
|
*/
|
|||
|
var rangeBitwiseAnd = function(m, n) {
|
|||
|
let count = 0;
|
|||
|
while (m !== n) {
|
|||
|
m = m >> 1;
|
|||
|
n = n >> 1;
|
|||
|
count++;
|
|||
|
}
|
|||
|
|
|||
|
return n << count;
|
|||
|
};
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
Python Code:
|
|||
|
|
|||
|
```python
|
|||
|
class Solution:
|
|||
|
def rangeBitwiseAnd(self, m: int, n: int) -> int:
|
|||
|
cnt = 0
|
|||
|
while m != n:
|
|||
|
m >>= 1
|
|||
|
n >>= 1
|
|||
|
cnt += 1
|
|||
|
|
|||
|
return m << cnt
|
|||
|
```
|
|||
|
|
|||
|
**复杂度分析**
|
|||
|
|
|||
|
- 时间复杂度:最坏的情况我们需要循环N次,最好的情况是一次都不需要, 因此时间复杂度取决于我们移动的位数,具体移动的次数取决于我们的输入,平均来说时间复杂度为 $O(N)$,其中N为M和N的二进制表示的位数。
|
|||
|
- 空间复杂度:$O(1)$
|
|||
|
|
|||
|
|