【专项刷题】— 位运算

常见类型介绍:

  1. & :有 0 就是 0
    | :有 1 就是 1
    ^ :相同为 0 ,相异为 1 或者 无进位相加
  2. 给定一个数确定它的二进制位的第x个数是0还是1:
  3. 将一个数的二进制的第x位改成1:
  4. 将一个数的二进制的第x位改成0:
  5. 提取一个数的二进制位的最右侧的1:
  6. 修改一个数的二进制位的最右侧的1:
  7.  ^  异或运算:

1、判定字符是否唯一 - 力扣(LeetCode)

思路:

  1. 解法一:哈希表(hash[26]表示一个哈希表)
  2. 解法二:使用位图,一个整型有三十二位比特位,用每个比特位存储的0 1来表示有没有重复
  3. 代码:
    public boolean isUnique(String astr) {
            int n = astr.length();
            char[] s = astr.toCharArray();
            //字符串长度大于26就肯定重复
            if(n > 26){
                return false;
            }
            int tmp = 0;
            for(int i = 0; i < n; i++){
                int x = s[i] - 'a';
                //先判断是否在位图中
                if(((tmp >> x) & 1) == 1){
                    return false;
                }
                //把当前字符添加到位图中
                tmp |= (1 << x);
            }
            return true;
        }

2、丢失的数字 - 力扣(LeetCode)

思路:

  1. 哈希表
  2. 高斯求和: ret = (0+5)(1+5)/2 - sum[nums]
  3. 位运算:消消乐
    代码:
    public int missingNumber(int[] nums) {
            int ret = 0;
            for(int x : nums){
                ret ^= x;
            }
            for(int i = 0; i <= nums.length; i++){
                ret ^= i;
            }
            return ret;
        }

3、两整数之和 - 力扣(LeetCode)

思路:

  • 运用异或的无进位相加和 (a&b) << 1 的有进位相加进行异或:
  • 代码:
    public int getSum(int a, int b) {
            while(b != 0){
                int x = a^b;
                int curry = (a&b) << 1;
                a = x;
                b = curry;
            }
            return a;
    }

4、只出现一次的数字 II - 力扣(LeetCode) 

思路:

  1. 统计nums中每个数的每一位的比特值的和,然后 %3(题意)
  2. 代码:
    public int singleNumber(int[] nums) {
            int ret = 0;
            //依次修改ret每一位的比特位(最终结果 )
            for(int i = 0; i < 32; i++){
                int sum = 0;
                //统计nums中数的每一位的比特位的值
                for(int x : nums){
                    if(((x >> i) & 1) == 1){
                        sum++;
                    }
                }
                sum %= 3;
                if(sum == 1){
                    ret |= (1 << i);
                }
            }
            return ret;
        }

5、消失的两个数字 - 力扣(LeetCode) 

思路:

  1. 首先将所有的数异或在一起,用tmp表示,nums里面的数和1到nums.length+2(原本数组长度就是现有的数组长度加2)
  2. 因为nums里面的数和1到nums.length+2里面的数有重复的,异或完之后就是0,剩下的就是消失的那两个数的异或,因为他们肯定不相等,所以某一位上肯定一个是1一个是0,找到这一位
  3. 根据这一比特位的不同,再分别进行异或,重复的数就异或成0,剩下的就把这两个数给去分开了
  4. 代码:
    public int[] missingTwo(int[] nums) {
            //先把所有的数异或在一起
            int tmp = 0;
            for(int x : nums){
                tmp ^= x;
            }
            for(int i = 1; i <= nums.length + 2; i++){
                tmp ^= i;
            }
            //找到比特位为一的那一位
            int deff = 0;
            while(true){
                if(((tmp >> deff) & 1) == 1){
                    break;
                }else{
                    deff++;
                }
            }
            //根据x位的不同,划分为两类异或
            int[] ret = new int[2];
            for(int x : nums){
                if(((x >> deff) & 1) == 1){
                    ret[1] ^= x;
                }else{
                    ret[0] ^= x;
                }
            }
            for(int i = 1; i <= nums.length + 2; i++){
                if(((i >> deff) & 1) == 1){
                    ret[1] ^= i;
                }else{
                    ret[0] ^= i;
                }
            }
            return ret;
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值