位运算相关题目
文章目录
- 位运算相关题目
- 一、基础内容
- 二、位运算的实战题目
- 2.1 [191. 位1的个数](https://leetcode-cn.com/problems/number-of-1-bits/)
- 2.2 [231. 2 的幂](https://leetcode-cn.com/problems/power-of-two/)
- 2.3 [190. 颠倒二进制位](https://leetcode-cn.com/problems/reverse-bits/)
- 2.5 [51. N 皇后](https://leetcode-cn.com/problems/n-queens/)
- 2.6 [52. N皇后 II](https://leetcode-cn.com/problems/n-queens-ii/)
- 2.7 [338. 比特位计数](https://leetcode-cn.com/problems/counting-bits/)
一、基础内容
1.1 为什么需要位运算
计算机内部是二进制
将十进制转换成二进制:不断除10,余数放最低位
1.2 位运算符
在计算机内部,老的计算机是32个二进制位,新的计算机是64个二进制位。
>>
右移,空出来的二进制位补0<<
左移|
按位或&
按位与~
按位取反^
按位异或(相同为0,不同为1)
1.3 异或的高级用法
x^0=x
x^1s(全1)=~x
(1s=~0)x^(~x)=1s
x^x=0
- 交换两位数:
a^b=c, a^c=b, b^c=a
- 结合法:
a^b^c=a^(b^c)=(a^b)^c
交换两个数,位元算,写法一:
int c = a^b;
a = a^c;
b = b^c;
交换两个数,位元算,写法二:
a = a^b;
b = a^b;
a = a^b;
1.4 指定位置的位运算
-
将x的最右边的n位清0:
x&(~0<<n)
-
获取x第n位的值(0或1):
(x>>n)&1
-
取x的第n位的幂值:
x&(1<<n)
-
仅将第n位置为1:
x|(1<<n)
-
仅将第n位置位0:
x&(~(1<<n))
-
将x最高位及第n位清零:
x&((1<<n)-1)
1.5 (重点)实战要点
-
判断奇偶:
x%2==1
<==>x&1==1
x%2==0
<==>x&1==0
-
x>>1
<==>x/2
既:
mid=(left+right)/2
==》mid=(left+right)>>1
-
清零最低位的1:
x&(x-1)
-
得到最低位的1:
x&(-x)
-
x&~x=0
x^x=0
二、位运算的实战题目
2.1 191. 位1的个数
解法一:转化成二进制字符串,然后计数1的个数
public int hammingWeight(int n) {
String str = Integer.toBinaryString(n);
int res = 0;
for (int i=0; i<str.length(); i++) {
if (str.charAt(i)=='1') res++;
}
return res;
}
解法二:位运算,&1
,然后>>>1
, 高位补零
public int hammingWeight(int n) {
int res = 0;
while (n!=0) {
if ((n&1)==1) {
res++;
}
n=n>>>1;
}
return res;
}
解法三:每次清零最低位的1
public int hammingWeight(int n) {
int res = 0;
while (n!=0) {
n = n & (n-1);
res++;
}
return res;
}
2.2 231. 2 的幂
解法一:位元算,二进制位有且仅有一位是1
public boolean isPowerOfTwo(int n) {
return n>0 && (n&(n-1))==0;
}
2.3 190. 颠倒二进制位
解法一:位元算
public int reverseBits(int n) {
int res = 0;
for (int i=0; i<32; i++) {
res = (res<<1)+(n&1);
n=n>>1;
}
return res;
}
2.5 51. N 皇后
解法一:Java的解法
private Set<Integer> lies = new HashSet<>();
private Set<Integer> pies = new HashSet<>();
private Set<Integer> nas = new HashSet<>();
public List<List<String>> solveNQueens(int n) {
List<int[]> res = new ArrayList<>();
solve(res, 0, n, new int[n]);
List<List<String>> resList = changeRes(res, n);
return resList;
}
private List<List<String>> changeRes(List<int[]> res, int n) {
List<List<String>> resList = new ArrayList<>(res.size());
for (int[] a: res) {
List<String> item = new ArrayList<>();
for (int k:a) {
char[] ca = new char[n];
Arrays.fill(ca, '.');
ca[k]='Q';
item.add(String.valueOf(ca));
}
resList.add(item);
}
return resList;
}
private void solve(List<int[]> res, int row, int n, int[] a){
if (row>=n) {
res.add(a.clone());
return;
}
for (int col=0; col<n; col++) {
if (lies.contains(col) || pies.contains(col+row) || nas.contains(col-row)) continue;
lies.add(col);
pies.add(col+row);
nas.add(col-row);
a[row] = col;
solve(res, row+1, n, a);
lies.remove(col);
pies.remove(col+row);
nas.remove(col-row);
}
}
解法二:python的简洁解法
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
def solve(lies, pies, nas):
if len(lies)==n:
res.append(lies);
return
for i in range(n):
if i not in lies and (len(lies)+i) not in pies and (len(lies)-i) not in nas:
solve(lies+[i], pies+[len(lies)+i], nas+[len(lies)-i]);
res=[]
solve([],[],[])
return [['.'*k+'Q'+'.'*(n-k-1) for k in r]for r in res]
2.6 52. N皇后 II
解法一:二进制解法:得到最低位的1、打掉最低位的1
private int count;
public int totalNQueens(int n) {
solve(0, n, 0, 0, 0);
return count;
}
private void solve(int row, int n, int lies, int pies, int nas) {
if (row>=n) {
count += 1;
return;
}
// 可以放皇后的位置
int p = (~(lies|pies|nas)) & ((1<<n)-1);
while (p!=0) {
// 取最低位的1
int k = p & (-p);
// 打掉最低位的1, 意味着放上皇后
p = p & (p-1);
solve(row+1, n, lies|k, (pies|k)<<1, (nas|k)>>1);
}
}
2.7 338. 比特位计数
解法一:位运算,打掉最低位的1
public int[] countBits(int n) {
int[] res = new int[n+1];
for (int i=0; i<=n; i++) {
int k = 0, t = i;
while (t!=0) {
t = t & (t-1);
k++;
}
res[i]= k;
}
return res;
}