(基于Java)算法笔记——位运算问题

位运算问题算法简略记录

1、常用技巧

  • 利用二进制进行计算
  • 运算符号:^按位异或;&按位与;|按位或;~取反;<<算术左移;>>算术右移
  • 常见特性(0s/1s分别代表只由0或1构成的二进制数):
    • x ^ 0s = xx ^ 1s = ~xx ^ x = 0
    • x & 0s = 0x & 1s = xx & x = x
    • x | 0s = xx | 1s = 1x | x = x
  • n & (n-1):能去除n的位级中最低的那一位
    • n = 11110100n-1 = 11110011n & (n-1) = 11110000
    • 即,将n中最低位级,第三位的1去除了
  • n & (-n):可以得到n的位级中最低的那一位
    • n = 11110100-n = 00001100n & (-n) = 00000100
    • 即,将仅保留了n中最低位级

2、基础问题

① LeetCode 461 汉明距离

解题思路

  • 对两个数进行按位异或,统计共有多少个1即可

Java解答

class Solution {
    public int hammingDistance(int x, int y) {
        int distance = x ^ y;
        int count = 0;
        while (distance > 0) {
            if (distance % 2 == 1) count++;
            distance /= 2;
        }
        return count;
    }
}

② LeetCode 190 颠倒二进制位

解题思路

  • 注:输入的是32位的01进制数
  • 使用算术左移和右移
    • ans = n & 1为,将n的最低位赋予ans
    • ans与n一个算术左移乘2、一个算术右移除2
public class Solution {
    // you need treat n as an unsigned value
    public int reverseBits(int n) {
        int ans = 0;
        for (int i = 0; i < 32; i++) {
            ans <<= 1;
            ans += n & 1;
            n >>= 1;
        }
        return ans;
    }
}

③ LeetCode 136 只出现一次的数字

解题思路

  • 利用x ^ x = 0x ^ 0 = x的特点进行遍历数组;有x ^ y ^ x = y
    • 如nums=[4, 2, 1, 2, 4],有4 ^ 2 ^ 1 ^2 ^ 4 = 1

Java解答

class Solution {
    public int singleNumber(int[] nums) {
        int ans = 0;
        for (int num : nums) {
            ans ^= num;
        }
        return ans;
    }
}

3、二进制特性

如,二进制+位运算=数组的所有子集

  • 长度为n的数组,生成长度为n的所有二进制,1表示选取该数字,0表示不选取,即可获得2^n个子集

① LeetCode 342 4的幂

解题思路

  • 首先考虑2的次方n,其二进制的一定是0…010…0;n-1则为0…001…1;则有n&(n-1)=0
  • 其次考虑4的次方m,相较与2的次方n,n中所有1所处的位置在奇数位;将m与1431655765按位与,结果不为零即为4的次方

Java解答

class Solution {
    public boolean isPowerOfFour(int n) {
        return (n > 0) && ((n & (n - 1)) == 0) && ((n & 1431655765) != 0);
    }
}

② LeetCode 318 最大单词长度乘积

解题思路

  • 首先为每个字符串建立长度为26的二进制数字;每个位置表示是否存在该字母
  • 如果两个字符串含有重复的字母,二进制数字的按位与不为0
  • 同时建立一个哈希表存储字母串到二进制数字的映射关系
  • 预计算所有单词的位掩码,并将它们存储在 HashMap 中:位掩码 -> 该掩码对应的最大长度字符串。例如:单词 “aaaaaaa” 和 “a” 具有相同的掩码。
  • 逐一两两比较 HashMap 中的单词。如果两个单词没有公共字母,更新最大单词长度乘积 maxProd。使用位掩码可以在常数时间内判断两个单词是否包含公共字母:(x & y) == 0

Java解答

class Solution {
    public int bitNumber(char ch){
        return (int)ch - (int)'a';
    }

    public int maxProduct(String[] words) {
        Map<Integer, Integer> hashmap = new HashMap();

        int bitmask = 0, bitNum = 0;
        for (String word : words) {
            bitmask = 0;
            for (char ch : word.toCharArray()) {
                // add bit number bitNumber in bitmask
                bitmask |= 1 << bitNumber(ch);
            }
            // there could be different words with the same bitmask
            // ex. ab and aabb
            hashmap.put(bitmask, Math.max(hashmap.getOrDefault(bitmask, 0), word.length()));
        }

        int maxProd = 0;
        for (int x : hashmap.keySet())
            for (int y : hashmap.keySet())
                if ((x & y) == 0) maxProd = Math.max(maxProd, hashmap.get(x) * hashmap.get(y));

        return maxProd;
    }
}

③ LeetCode 338 比特位计数

解题思路

  • 由于n & (-n)为取n的最低位级的1;循环遍历,每有一个1,计数加一,n再减去最低位级代表的数

Java解答

class Solution {
    public int[] countBits(int n) {
        int[] ans = new int[n+1];
        for (int i = 0; i <= n; i++) {
            ans[i] = bits(i);
        }
        return ans;
    }

        private int bits(int n) {
            int count = 0;
            while (n > 0) {
                if ((n & (-n)) != 0) {
                    count++;
                }
                n = n - (n & (-n));
            }
            return count;
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值