今日得到: 位运算真的是 666, 计算机基础还有数学知识都很重要.
LeetCode-191 二进制位1的个数LeetCode上第 191 号问题:编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数。
观察一下 n 与 n-1 这两个数的二进制表示:对于 n-1 这个数的二进制来说,相对于 n 的二进制,它的最末位的一个 1 会变成 0,最末位一个 1 之后的 0 会全部变成 1,其它位相同不变。
比如 n = 8888,其二进制为 10001010111000
则 n - 1 = 8887 ,其二进制为 10001010110111
通过按位与操作后:n & (n-1) = 10001010110000
也就是说:通过 n&(n-1)这个操作,可以起到消除最后一个1的作用。
所以可以通过执行 n&(n-1) 操作来消除 n 末尾的 1 ,消除了多少次,就说明有多少个 1 。
class Solution: def hammingWeight(self, n): res = 0 while n != 0: res += 1 n &= (n - 1) return res def hammingWeight2(self, n): res = 0 while n != 0: res += (n & 1) n = n >> 1 return res算法-求二进制数中1的个数 多种解法
LeetCode-231 2的幂给定一个整数,编写一个函数来判断它是否是 2 的幂次方。
仔细观察,可以看出 2 的次方数都只有一个 1 ,剩下的都是 0 。根据这个特点,只需要每次判断最低位是否为 1 ,然后向右移位,最后统计 1 的个数即可判断是否是 2 的次方数, 可以使用上一个问题的解法
def isPowerOfTwo(n): res = 0 while n != 0: res += (n & 1) n >>= 1 return res == 1该题还有一种巧妙的解法。再观察上面的表格,如果一个数是 2 的次方数的话,那么它的二进数必然是最高位为1,其它都为 0 ,那么如果此时我们减 1 的话,则最高位会降一位,其余为 0 的位现在都为变为 1,那么我们把两数相与,就会得到 0.
图片来源
比如 2 的 3 次方为 8,二进制位 1000 ,那么 8 - 1 = 7,其中 7 的二进制位 0111
class Solution: def isPowerOfTwo(self, n: int) -> bool: return (n > 0) and ((n & (n - 1)) == 0) LeetCode-201. 闭区间范围内数字按位与给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)
所有这些位字符串的公共前缀也是指定范围的起始和结束编号的公共前缀(即在上面的示例中分别为 9 和 12),因此,我们可以将问题重新表述为:给定两个整数,要求我们找到她们二进制字符串的公共前缀
使用191的方法 Brian Kernighan 算法 n & (n-1)
class Solution: def rangeBitwiseAnd(self, m: int, n: int) -> int: while m < n: # turn off rightmost 1-bit n = n & (n - 1) return m & n找m, n 的最高位1出现的位置 , 如果不相等,则返回0,如果相等,则找公共前缀。B站视频-位运算练习【LeetCode】
LeetCode-187.重复的DNA序列所有 DNA 都由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。
编写一个函数来查找目标子串,目标子串的长度为 10,且在 DNA 字符串 s 中出现次数超过一次。差点没看懂题 QAQ!
输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT" 输出:["AAAAACCCCC", "CCCCCAAAAA"] # 普通解法 class Solution: def findRepeatedDnaSequences(self, s: str) -> List[str]: d = {} for i in range(len(s) - 9): k = s[i: i+10] if k in d: d[k] = True else: d[k] = False return [*filter(lambda x: d[x], d)]该的位运算解法暂时没看懂,先记录着,有点晕了,后面继续看
题解
LeetCode-36.只出现一次的数字给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
要求: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
输入: [2,2,1] 输出: 1 输入: [4,1,2,1,2] 输出: 4这题比较简单,想到异或运算,相同为0,不同为1的规则就可以很快求解了
a b a⊕b1 0 1
1 1 0
0 0 0
0 1 1
class Solution: def singleNumber(self, nums: List[int]) -> int: # 非空数组暂时不用判断 from functools import reduce return reduce(lambda a, b: a ^ b, nums) LeetCode-137.只出现一次的数字 II
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
要求: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
输入: [2,2,3,2] 输出: 3 输入: [0,1,0,1,0,1,99] 输出: 993×(a+b+c)−(a+a+a+b+b+b+c)=2c 也可以应用在上一题
## 普通解法 class Solution: def singleNumber(self, nums): return (3 * sum(set(nums)) - sum(nums)) // 2推广到一般情况: