位运算
Posted mgblogs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了位运算相关的知识,希望对你有一定的参考价值。
位运算主要有以下几方式
- 位的提取(把每一位提取出来)
- 字符串匹配,感觉在位运算中使用字符串很好用
- 异或运算去重复,异或代替其他运算,总之异或很重要
一、常用的知识点
(1)位操作
| 与运算:与运算用来置位
& 并运算:并运算用来掩码,n&(-n)可以获得最低位的1
~取反:用的很少
^异或运算:异或运算通常用来去重复 a^a=0
>>> 逻辑右移:高位补0
>>算数右移:补符号位
<<算数左移:补0
(2)Java中常用库函数
Integer.bitCount(int i):统计1的位数
Integer.highestOneBit(int i):取得最高位的1的int值
Integer.lowestOneBit(int i):取得最低位的1的int值
Integer.toString(int i, int radix):int转成radix进制的String
Integer.parseInt(String s, int radix):String转成让radix进制的int
二、类型题
(1)位的提取
使用&与>>>提取n中的每一位,当然也可以使用Integer.bitCount();
class Solution { public int hammingDistance(int x, int y) { int n = x^y; int count = 0; while(n!=0) { if((n&1) == 1) count++; n = n >>> 1; } return count; } }
相比与1在位运算中多使用0更好,一串0比一串1更好用int来表示
public class Solution { // you need treat n as an unsigned value public int reverseBits(int n) { int ans = 0; for(int i = 1; i <= 32; i++) { ans = ans << 1; ans = ans | (n&1); n = n >>> 1; } return ans; } }
(2)使用^去重复
位运算的题一般也有提示:不使用额外空间、线性复杂度
class Solution { public int singleNumber(int[] nums) { int ans = nums[0]; for(int i = 1; i < nums.length; i++) { ans = ans^nums[i]; } return ans; } }
这个题O(n)时间复杂度用位运算,O(logn)则使用二分法
class Solution { public int missingNumber(int[] nums) { int ans = 0; for(int i = 0; i < nums.length; i++) { ans = ans^i^nums[i]; } return ans^nums.length; } }
class Solution { public int[] singleNumber(int[] nums) { int diff = 0; for(int num : nums) { diff ^= num; } diff = Integer.lowestOneBit(diff);//提取最右边的一位1 int[] ans = new int[2]; for(int num : nums) { if((num&diff)==0) ans[0] ^= num; else ans[1] ^= num; } return ans; } }
(3)异或代替其他运算
不用额外变量交换a与b
public class Test { public static void main(String[] args) { int a = 2; int b = 5; a = a^b; b = a^b; a = a^b; System.out.println("a = " + a); System.out.println("b = " + b); } }
不用+-算加减
class Solution { public int getSum(int a, int b) { return b == 0 ? a : getSum(a^b,(a&b)<<1); } }
(4)使用字符串匹配
字符串匹配虽然没有位运算性能好,但它简单啊
class Solution { public boolean isPowerOfTwo(int n) { return n>0 && Integer.toString(n,2).matches("0*10*"); } }
位运算
class Solution { public boolean isPowerOfTwo(int n) { if(n < 0) return false; return Integer.bitCount(n) == 1 ? true : false; } }
位运算
class Solution { public boolean isPowerOfFour(int num) { return num>0&&Integer.bitCount(num)==1&&((num&0b01010101010101010101010101010101)!=0); } }
字符串
public boolean isPowerOfFour(int num) { return Integer.toString(num, 4).matches("10*"); }
class Solution { public boolean hasAlternatingBits(int n) { return Integer.toString(n,2).matches("1(01)*0?"); } }
class Solution { public int findComplement(int num) { String s = Integer.toString(num,2); StringBuilder ans = new StringBuilder(s); for(int i = 0; i < ans.length(); i++) { if(ans.charAt(i) == ‘1‘) ans.setCharAt(i,‘0‘); else ans.setCharAt(i,‘1‘); } return Integer.parseInt(new String(ans),2); } }
(5)用二进制的每一位充当字母的映射表
class Solution { public int maxProduct(String[] words) { int[] meme = new int[words.length]; for(int i = 0; i < words.length; i++) { for(int j = 0; j < words[i].length(); j++) { meme[i] = meme[i] | (1 << words[i].charAt(j) - ‘a‘); } } int ans = 0; for(int i = 0; i < words.length-1; i++) { for(int j = i+1; j < words.length; j++) { if((meme[i] & meme[j]) == 0) ans = Math.max(ans,words[i].length()*words[j].length()); } } return ans; } }
以上是关于位运算的主要内容,如果未能解决你的问题,请参考以下文章