每天告诉自己一次,“我真的很不错”。
题目描述
给定范围 [m, n],其中m、n为不超出计算范围的正整数,返回此范围内所有数字按位与的结果(包含 m, n 两端点)。
答案
var rangeBitwiseAnd = function(m, n) {
let shift = 0;
// 找到公共前缀
while (m < n) {
m >>= 1;
n >>= 1;
++shift;
}
return m << shift;
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/bitwise-and-of-numbers-range/solution/shu-zi-fan-wei-an-wei-yu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
结论
给定两个整数,我们要找到它们对应的二进制字符串的公共前缀。没有则为0
解题思路
将问题重新表述为:给定两个整数,我们要找到它们对应的二进制字符串的公共前缀。
对所有数字执行按位与运算的结果是所有对应二进制字符串的公共前缀再用零补上后面的剩余位。
那么这个规律是否正确呢?我们可以进行简单的证明。假设对于所有这些二进制串,前 ii 位均相同,第 i+1i+1 位开始不同,由于 [m,n][m,n] 连续,所以第 i+1i+1 位在 [m,n][m,n] 的数字范围从小到大列举出来一定是前面全部是 00,后面全部是 11,在上图中对应 [9,11][9,11] 均为 00,[12,12][12,12] 均为 11。并且一定存在连续的两个数 xx 和 x+1x+1,满足 xx 的第 i+1i+1 位为 00,后面全为 11,x+1x+1 的第 i+1i+1 位为 11,后面全为 00,对应上图中的例子即为 1111 和 1212。这种形如 0111 \ldots0111… 和 1000 \ldots1000… 的二进制串的按位与的结果一定为 0000 \ldots0000…,因此第 i+1i+1 位开始的剩余位均为 00,前 ii 位由于均相同,因此按位与结果不变。最后的答案即为二进制字符串的公共前缀再用零补上后面的剩余位。
官方一顿操作,没人懂这分析过程,嗐。改日再看