位运算?我直接刷爆

文章介绍了位运算在编程中的实际应用,包括通过位运算判断一个数的奇偶性,清除最低位的1,以及计算二进制中1的个数(汉明重量)。此外,还展示了如何使用位运算判断一个数是否为2的幂次方,并提供了C++、Java和Python的AC代码。最后,提到了位运算在解决N皇后问题中的作用。
摘要由CSDN通过智能技术生成

csdn

位运算(Bitwise operations)

数据结构简介…

实战中常用的位运算操作:

位运算描述
x & 1 == 1 OR == 0判断奇偶
x = x & (x - 1)清零最低位的1
x & -x得到最低位的1

高频面试题

1.位1的个数

🚀题目链接:LeetCode191.位1的个数

题目:
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

提示:

  • 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
  • 在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在上面的 示例 3 中,输入表示有符号整数 -3。

示例 1:

输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'

示例 2:

输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'

示例 3:

输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'

🍬C++ AC代码:

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int cnt = 0;
        while (n != 0) {
            n = n & (n - 1);
            cnt++;
        }
        return cnt;
    }
};

Java AC代码:

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int cnt = 0;
        while (n != 0) {
            n = n & (n - 1);
            cnt++;
        }
        return cnt;
    }
}

🍦Python AC代码:

class Solution(object):
    def hammingWeight(self, n):
        cnt = 0
        while n != 0:
            n, cnt = n & (n - 1), cnt + 1
        return cnt

2. 2 的幂

🚀题目链接:LeetCode231.2 的幂

题目:

给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false
如果存在一个整数 x 使得 n == 2x ,则认为 n2 的幂次方。

示例 1:

输入:n = 1
输出:true
解释:20 = 1

示例 2:

输入:n = 16
输出:true
解释:24 = 16

示例 3:

输入:n = 3
输出:false

Tips:

  • ⭐二进制中如果一个数是2的幂次方,那么二进制位中有且仅有一个1
  • ⭐上面一题中使用的二进制运算x & (x-1)可以去掉x中二进制位的最后一个1,本题我们可以借助它来判断给定的数二进制中是不是只有一个1
  • ⭐这种方法时间复杂度只需要 O ( 1 ) O(1) O(1)

🍬C++ AC代码:

class Solution {
public:
    bool isPowerOfTwo(int n) {
        return n != 0 && (n & ((long)n - 1)) == 0;
    }
};

Java AC代码:

class Solution {
    public boolean isPowerOfTwo(int n) {
        return n != 0 && (n & ((long)n - 1)) == 0;
    }
}

🍦Python AC代码:

class Solution(object):
    def isPowerOfTwo(self, n):
        return n != 0 and (n & (n - 1)) == 0


3.比特位计数

🚀题目链接:LeetCode337.比特位计数

题目:
给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

示例 1:

输入:n = 2
输出:[0,1,1]
解释:
0 --> 0
1 --> 1
2 --> 10

示例 2:

输入:n = 5
输出:[0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101

Tips:

  • ⭐还是上面两道题的办法,我们知道二进制运算i & (i-1)可以去掉i中二进制位的最后一个1
  • ⭐初始化一个count[n+1]数组保存1~n每个数的二进制有多少个1,使用递推公式count[i] = count[i & (i-1)] + 1计算每一个数有多少个二进制1
  • i & (i-1)肯定小于i,因此我们只需要得到i去掉二进制位最后一个1所对应的数有多少个二进制1,然后再加上去掉的那一个1,就是i的二进制位中1的个数。

🍬C++ AC代码:

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int> count(n + 1, 0);
        for (int i = 1; i <= n; i++)
            count[i] = count[i & (i - 1)] + 1;
        return count;
    }
};

Java AC代码:

class Solution {
    public int[] countBits(int n) {
        int[] count = new int[n + 1];
        for (int i = 1; i <= n; i++)
            count[i] = count[i & (i - 1)] + 1;
        return count;
    }
}

🍦Python AC代码:

class Solution(object):
    def countBits(self, n):
        count = [0]
        for i in range(1, n + 1):
            count.append(count[i & (i - 1)] + 1)
        return count

🎈PS.N皇后的另外一种解法

🚀题目链接:LeetCode52.N皇后 II

题目:
n 皇后问题 研究的是如何将 n 个皇后放置在 n × n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。

示例 1:
1

输入:n = 4
输出:2
解释:如上图所示,4 皇后问题存在两个不同的解法。

DFS核心代码:

DFS

Tips:

  • ⭐用coldiag1diag2的二进制位保存当前行可以被皇后攻击到的位置,二进制的第 i i i位是1,则表示位置 i i i会被其他皇后攻击,其中col表示列,diag1diag2代表左斜方向与右斜方向。
  • col | diag1 | diag2三个进行或运算,得到当前能被攻击到的位置,再取反,将可以放置皇后的位置置为1,由于我们只用到二进制位的前n个位置,因此将后面的二进制全部置为0,取反后还要和(1 << N) - 1相与。
  • bits & -bits得到bits最末尾的1的位置p,也就是我们可以放置皇后的位置。
  • ⭐递归调用dfs,我们在p位置放置了皇后,因此参数要更新,coldiag1diag2分别或运算即可,同时注意到diag1diag2表示左右斜方向能攻击到的位置,还要多一个左移和右移一位的操作。

🍬C++ AC代码:

class Solution {
public:
    int count = 0;

    int totalNQueens(int n) {
        if (n < 1) return 0;
        dfs(n, 0, 0, 0, 0);
        return count;
    }

    void dfs(int n, int row, int cols, int diag1, int diag2){
        if (row >= n) {
            count++;
            return;
        }
        int bits = (~(cols | diag1 | diag2)) & ((1 << n) - 1);
        while (bits > 0) {
            int p = bits & -bits;
            dfs(n, row + 1, cols | p, (diag1 | p) << 1, (diag2 | p) >> 1);
            bits = bits & (bits - 1);
        }
    }
};

Java AC代码:

class Solution {
    
    int count = 0;

    public int totalNQueens(int n) {
        if (n < 1) return 0;
        dfs (n, 0, 0, 0, 0);
        return count;
    }

    public void dfs(int n, int row, int cols, int diag1, int diag2){
        if (row >= n) {
            count++;
            return;
        }
        int bits = (~(cols | diag1 | diag2)) & ((1 << n) - 1);
        while (bits > 0) {
            int p = bits & -bits;
            dfs(n, row + 1, cols | p, (diag1 | p) << 1, (diag2 | p) >> 1);
            bits = bits & (bits - 1);
        }
    }
}

🍦Python AC代码:

class Solution(object):
    def totalNQueens(self, n):
        if n < 1: return []
        self.count = 0;
        self.DFS(n, 0, 0, 0, 0)
        return self.count

    def DFS(self, n, row, cols, diag1, diag2):
        if row >= n:
            self.count += 1
            return
        bits = (~(cols | diag1 | diag2)) & ((1 << n) - 1)
        while bits:
            p = bits & -bits
            self.DFS(n, row + 1, cols | p, (diag1 | p) << 1, (diag2 | p) >> 1)
            bits = bits & (bits - 1)

总结

┊事皆前定,谁弱又谁强;且趁闲身未老,尽放我、些子疏狂┊
-苏轼·满庭芳-

footer

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值