defbitset_union(bitset1, bitset2): """位图并集运算""" result = Bitset(max(len(bitset1.set), len(bitset2.set)) * 32) for i inrange(min(len(bitset1.set), len(bitset2.set))): result.set[i] = bitset1.set[i] | bitset2.set[i] return result
defbitset_intersection(bitset1, bitset2): """位图交集运算""" result = Bitset(max(len(bitset1.set), len(bitset2.set)) * 32) for i inrange(min(len(bitset1.set), len(bitset2.set))): result.set[i] = bitset1.set[i] & bitset2.set[i] return result
@staticmethod defadd(a, b): """位运算实现加法""" #单次相加的结果为:无进位相加的结果+进位信息 ans = a while b != 0: # 当b为0时,说明没有进位了,加法结束 # 单次进位只能把当前位的进位信息加到下一高位,但新一位的进位可能和更高位产生新的进位冲突,需要继续处理。 # 只有所有进位都为0,结果才是完整无误的。 # ans : a和b无进位相加的结果 ans = a ^ b # b : a和b相加时的进位信息 b = (a & b) << 1 # Python中int无限大,为了模拟int32,需要对超出部分进行处理 # 下面两行确保ans和b都保持32位 ans &= 0xFFFFFFFF b &= 0xFFFFFFFF a = ans # 处理负数转为补码 return ans if ans <= 0x7FFFFFFFelse ~(ans ^ 0xFFFFFFFF) #结果超过最大值时,需要将无符号32位结果转换为有符号,当加法结果超过0x7FFFFFFF时,实际上表示的是负数,需要转换为对应的有符号表示 #将ans与全1进行异或,相当于按位取反,~(...):再次取反,相当于恢复原值
@staticmethod defdivide(a, b): """主除法函数,处理各种边界情况""" # 处理 a 和 b 都为最小值的情况 if a == BitOperationAddMinusMultiplyDivide.MIN and b == BitOperationAddMinusMultiplyDivide.MIN: # a和b都是整数最小 return1 # 处理 a 和 b 都不是最小值的情况 if a != BitOperationAddMinusMultiplyDivide.MIN and b != BitOperationAddMinusMultiplyDivide.MIN: # a和b都不是整数最小,那么正常去除 return BitOperationAddMinusMultiplyDivide.div(a, b) # 处理 b 为最小值的情况 if b == BitOperationAddMinusMultiplyDivide.MIN: # a不是整数最小,b是整数最小,整数最小值是负数,而且整数最小值无法转成相反数 return0 # 处理 a 为最小值,b 为 -1 的情况(防止溢出) # 第1个if不成立:a 和 b 不都是最小值;第2个if不成立:a 和 b 不都不是最小值;第3个if不成立:b 不是最小值,则排除完b,a就是最小值 if b == BitOperationAddMinusMultiplyDivide.neg(1): # a是整数最小,b是-1,返回整数最大,因为题目里明确这么说了 return BitOperationAddMinusMultiplyDivide.MAX # a是整数最小,b不是整数最小,b也不是-1 a = BitOperationAddMinusMultiplyDivide.add(a, b if b > 0else BitOperationAddMinusMultiplyDivide.neg(b)) #让 a 不再是最小值,这样就可以安全地调用 div 函数了,如果 b > 0:a = a + b;如果 b < 0:a = a + (-b) ans = BitOperationAddMinusMultiplyDivide.div(a, b) # 现在 a 不再是最小值,可以安全地调用 div 函数 offset = BitOperationAddMinusMultiplyDivide.neg(1) if b > 0else1# 如果 b > 0,则 offset = -1;如果 b < 0,则 offset = 1 return BitOperationAddMinusMultiplyDivide.add(ans, offset) # 最后把 offset 加回去
核心除法算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
@staticmethod defdiv(a, b): #向下取整,但是不返回余数 """核心除法实现,要求a和b都不是整数最小值""" x = BitOperationAddMinusMultiplyDivide.neg(a) if a < 0else a # 取绝对值 y = BitOperationAddMinusMultiplyDivide.neg(b) if b < 0else b # 取绝对值 ans = 0 i = 30 while i >= 0: # (x >> i) >= y 时,说明y << i 还能减掉 if (x >> i) >= y: #判断x右移i位后是否大于等于y,若大于则记录1 ans |= (1 << i) # 记录这个位 x = BitOperationAddMinusMultiplyDivide.minus(x, y << i) # x 减去 y << i,即y*2^i i = BitOperationAddMinusMultiplyDivide.minus(i, 1) # 相当于 i-- # 最后根据正负判断符号 return BitOperationAddMinusMultiplyDivide.neg(ans) if (a < 0) ^ (b < 0) else ans #当两个数的符号不同时,结果取负;当符号相同时,结果保持正。