这篇文章,我在豆包MarsCode AI刷题(代码练习)题库中位运算分类下选取简单题、中等题、困难题各一道进行解析。
简单题
说实话,简单题中,只要不是题目出错,你教给MarsCode AI,它基本上都能给你解决。
找单独的数
问题描述
在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。
要求:
- 设计一个算法,使其时间复杂度为 O(n),其中 n 是班级的人数。
- 尽量减少额外空间的使用,以体现你的算法优化能力。
约束条件
- 1 ≤ cards.length ≤ 1001
- 0 ≤ cards[i] ≤ 1000
- 班级人数为奇数
- 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次
思路
最简单的一个思路,统计每个数组出现多少次,然后遍历查找出现1次的数字。
当然,题目要求题目要求尽量减少额外空间的使用,以体现我们的算法优化能力。
这里我们还可以使用位运算,我们知道 a ^ a = 0 所以,我们很快就能得出,将所有数字进行异或操作能马上得出结果。
代码
def solution(inp):
result = 0
for i in inp:
result ^= i
return result
中等题
判断子数组能否被5整除的问题
问题描述
小R有一个二进制数组 nums,其中的下标从 0 开始。我们定义 xi 为从最高有效位到最低有效位的子数组 nums[0..i] 所表示的二进制数。例如,如果 nums = [1, 0, 1],那么 x0 = 1,x1 = 2,x2 = 5。
小R想知道,对于每个 xi,它能否被 5 整除。你需要返回一个布尔值列表 answer,当 xi 能够被 5 整除时,answer[i] 为 true,否则为 false。
思路
这题其实是一道简单题,我们只需要依次累左移,再加上当前的数字。
代码
def solution(nums: list) -> list:
now = 0
result = []
for i in nums:
now <<= 1
now += i
if now % 5 == 0:
result.append(bool(1))
else:
result.append(bool(0))
困难题
小k的区间与值和
问题描述
小K有一个数组,她定义数组的权值为数组中任选两个数的按位与的值之和。具体来说,对于数组中的每个连续子数组,我们可以计算所有可能的两个元素的按位与值之和,并将这些值相加。小K想知道该数组中所有可能的连续子数组的权值和是多少,最后结果对10^9 + 7取模。
思路
这题我们可以采用数学归纳法来做,我们看下面这个数组 xxxxaxxxxbxxxx,我们怎么求a & b 在每个连续子区间内出现多少次,首先 axxxxb是一定会出现的,对于这个数组左边可能会出现 "", "x", "xx", "xxx", "xxxx" 这几个,对于右边来说,可能是 "", "x", "xx", "xxx", "xxxx" 这几个,我们只要把两边数字相成就能得到哪些连续子区间内出现 a & b。所以,我们就能得到一个公式 (a & b) * pos(a) * (n - pos(b))
代码
def solution(n: int, a: list) -> int:
mod = 1e9 + 7
result = 0
for i in range(0, n - 1):
for j in range(i + 1, n):
result = (result + (a[i] & a[j]) * (i + 1) * (n - j)) % mod
return result