位运算

常见的位运算符
在这里插入图片描述

1.两整数之和(easy)

题目:不使用运算符 + 和 - ​​​​​​​,计算两整数 ​​​​​​​a 、b ​​​​​​​之和。
示例 1:
输入: a = 1, b = 2
输出: 3

思路:异或,可看作无进位的加法【输入十进制的话,^ 是将十进制转为二进制,在做异或得到的结果再转为十进制,二进制的话则直接异或输出。eg:1^ 3=2 ,0b01^ 0b11=2】;位与再左移,可以获取进位;
a + b 的问题拆分为 (a 和 b 的无进位结果) + (a 和 b 的进位结果)
tip:在 Python 中,整数不是 32 位的,一直循环左移并不会存在溢出的现象,这就需要我们手动对 Python 中的整数进行处理,手动模拟 32 位 int 整型。
具体做法是将整数对 0x100000000 取模,保证该数从 32 位开始到最高位都是 0。

def getSum(self, a: int, b: int) -> int:
        MASK = 0x100000000			 # 2^32
        MAX_INT = 0x7FFFFFFF		 # 整型最大值
        MIN_INT = MAX_INT + 1
        while b != 0:
            carry = (a & b) << 1	 # 计算进位 
            a = (a ^ b) % MASK		 # 取余范围限制在 [0, 2^32-1] 范围内
            b = carry % MASK
        return a if a <= MAX_INT else ~((a % MIN_INT) ^ MAX_INT)   

2.2的幂(easy)

题目:给定一个整数,编写一个函数来判断它是否是 2 的幂次方。
示例 1:
输入: 1
输出: true
解释: 20 = 1

思路:对于N为2的幂的数,都有 N&(N-1)=0

  def isPowerOfTwo(self, n: int) -> bool:
        if n<=0:
            return False
        return (n&(n-1))==0

3.位1的个数(easy)

题目:编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。

思路:N&(N-1)会把最后一个 1 的位变成 0 ,以此来计算1的个数

 def hammingWeight(self, n: int) -> int:
        res=0
        while n!=0:
            res+=1
            n= n&(n-1)
        return res

4.只出现一次的数字(easy)

题目:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1

思路:采用异或,任何数与0异或等于本身,两数相同异或为0
可满足交换律和结合律 a^b ^c=(a ^c) ^b

  def singleNumber(self, nums: List[int]) -> int:
        x = 0
        for i in nums:
             x=x^i
        return x

5.只出现一次的数字 II(medium)

题目:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,3,2]
输出: 3

思路:数学方法:3(a+b+c)-(a+a+a+b+b+b+c)=2c

  def singleNumber(self, nums: List[int]) -> int:
        res = sum( set(nums))
        return int((res*3-sum(nums))/2)

6.二进制求和(easy)

题目:给你两个二进制字符串,返回它们的和(用二进制表示)。
输入为 非空 字符串且只包含数字 1 和 0。
示例 1:
输入: a = “11”, b = “1”
输出: “100”

思路:与上面题求两数和思路一致,将二进制转十进制,再用异或求和,位与加左移获得进位,最终返回的是二进制

class Solution:
    def addBinary(self, a, b) -> str:
        x, y = int(a, 2), int(b, 2)
        while y:   					#进位不为 0
            answer = x ^ y			#计算当前 x和 y 的无进位相加结果
            carry = (x & y) << 1	#计算当前 x和 y的进位:
            x, y = answer, carry
        return bin(x)[2:]`在这里插入代码片`

7.数组中两个数的最大异或值 (medium)

题目:给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 。
找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ≤ i, j < n 。
你能在O(n)的时间解决这个问题吗?
示例:
输入: [3, 10, 5, 25, 2, 8]
输出: 28
解释: 最大的结果是 5 ^ 25 = 28.

思路:时间限制在O(n),用暴力法两次循环肯定会超时。求两个数的最大异或值则即为找到最大的异或值,先找到最高位为1 的数,通过贪心算法的思想【就是尽可能地让最高位为1】,从左到右找到与这个最高位数异或为1 的数,不断筛选得到最终的结果
还有个公式: a ^ b = c , c ^ b = a

class Solution:
    def findMaximumXOR(self, nums: List[int]) -> int:
        res = 0
        mask = 0
        for i in range(30, -1, -1):
            mask |= (1 << i)
            s = set()    		 # 当前得到的所有前缀都放在哈希表中
            for num in nums:
                s.add(mask & num)
            temp = res | (1 << i) # 贪心算法思想,若全部前缀遍历完都不符合条件,这个数位上就是0,否则为1
            for prefix in s:
                if temp ^ prefix in s:
                    res = temp
                    break
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值