位移运算
功能
示例
位运算
判断n是否为2的幂次方
1101 0101 & 1101 0100 =
n > 0 && (n & (n - 1)) == 0;
n > 0 && (n & -n) == n;
进制转换 十进制转 x 进制
短除法:用十进制的数除以 x 取余,最后从下往上去余数
x进制转十进制
3.十进制转为负 x 进制
遇到了负进制数,我们取余的时候余数会出现负的情况,我们就要处理这个负数的情况。我们可以经过以下的变换:
经过这样的变换之后那么X-R就是正数了。那么我们也可以得到一个结论:当余数为负数时,余数=余数-除数(除数为负数),商=商+1 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public String baseNeg2 (int n) { StringBuilder sb = new StringBuilder (); if (n==0 )return "0" ; while (n!=0 ){ int mod = n % -2 ; n = n / -2 ; if (mod<0 ){ mod = mod + 2 ; n++; } sb.append(mod); } sb.reverse(); return sb.toString(); } }
小数点转二进制 案例:192.324(十进制)转为二进制
整数部分192(十进制)= 11000000(二进制)
小数部分0.324(十进制)= 0.324 * 2 = 0.648 = 整数部分 = 0
= 0.648 * 2 = 1.296 = 整数部分 = 1 = 0.296 * 2 = 0.592 = 整数部分 = 0 = 0.592 * 2 = 1.184 = 整数部分 = 1 = 0.184 * 2 = 0.368 = 整数部分 = 0 = 0.184 * 2 = 0.368 = 整数部分 = 0 ………直到*2=不带小数,从上到下取二进制即为小数部分 = 0101001011110001
不断取乘以2后的整数部分
二进制转小数 11000000.0101001011110001
整数部分 11000000(二进制)= 12^7 + 1 2^6 + …… + 1*2^0 = 64 + 128 = 192(十进制)
小数部分 0101001011110001(二进制)= 02^(-1) + 1 2^(-2) + 02^(-3) + 1 2^(-4) + 02^(-5) + 0 2^(-6) + …… + 1 * 2^(-16) = 192.32373046875
从左到右除以2^(n) n=[1,长度]
相关题目
位移
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution { public int hammingWeight0 (int n) { int ret = 0 ; int mask = 1 ; for (int i=0 ;i<32 ;i++){ if ((n&mask)!=0 )ret++; mask<<=1 ; } return ret; } public int hammingWeight (int n) { int sum = 0 ; while (n != 0 ) { n &= (n - 1 ); sum++; } return sum; } }
(x & (-x)) == x (x & (x - 1)) == 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution { public boolean isPowerOfTwo (int n) { if (n == 0 ) return false ; long x = (long ) n; return (x & (-x)) == x; } public boolean isPowerOfTwo (int n) { if (n == 0 ) return false ; long x = (long ) n; return (x & (x - 1 )) == 0 ; } }
1011 & 0001 = 0001 获取末尾二进制值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Solution { public int reverseBits (int n) { int result = 0 ; for (int i = 0 ; i < 32 ; i++) { result <<= 1 ; result += 1 & n; n >>= 1 ; } return result; } public int reverseBits (int n) { int result = 0 ; for (int i = 0 ; i < 32 ; i++) { result <<= 1 ; result |= n & 1 ; n >>= 1 ; } return result; } }
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
x>>1右移1位(除以2),x&1取末位
P(x)=P(x&(x−1))+1;
1 2 3 4 5 6 7 8 public class Solution { public int [] countBits(int num) { int [] ans = new int [num + 1 ]; for (int i = 1 ; i <= num; ++i) ans[i] = ans[i >> 1 ] + (i & 1 ); return ans; } }
解题思路
数组列表进行异或即可得出只出现一次的数字
a
b
a⊕b
0
0
0
0
1
1
1
0
1
1
1
0
1 2 3 4 5 6 7 8 9 10 class Solution { public int singleNumber (int [] nums) { int ans = 0 ; for (int i=0 ;i<nums.length;i++){ ans = ans^nums[i]; System.out.println(ans); } return ans; } }
解题思路
将我们的数的二进制位每一位相加,然后对其每一位的和取余
如果输入是:nums = [2,2,3,2],那么它的各个元素对应的32位二进制数就是
1 2 3 4 5 6 [ 0000 0000 0000 0000 0000 0000 0000 0010 , 0000 0000 0000 0000 0000 0000 0000 0010 , 0000 0000 0000 0000 0000 0000 0000 0011 , 0000 0000 0000 0000 0000 0000 0000 0010 ]
接着,对这些二进制数的对应位进行求和,得到: [00000000000000000000000000000041]; 对这个求和结果的每一位进行3的取模运算,得到:[00000000000000000000000000000011]; 把上面的结果从二进制转换为十进制,就是:3。这就是我们的答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public int singleNumber (int [] nums) { int res = 0 ; for (int i = 0 ; i < 32 ; i++){ int count = 0 ; for (int j = 0 ; j < nums.length; j++) { if ((nums[j] >> i & 1 ) == 1 ) { count++; } } if (count % 3 != 0 ) { res = res | 1 << i; } } return res; } }
解题思路
有两个数只出现了一次记为 num1、num2 初始化为 0, 其余的数出现了两次,我们可以对所有的数进行一次异或操作, 易知这个结果就等于 num1 和 num2 的异或结果(相同的数异或结果都为 0, 0和任意数异或结果都为那个数).
那么我们可以考虑异或结果的某个非 0 位如最后一个非 0 位, 因为我们知道只有当 num1、num2 在该位不一样的时候才会出现异或结果为 1. 所以我们以该位是否为 1 对数组进行划分, 只要该位为 1 就和 num1 异或, 只要该位为 0就和 num2 异或, 这样最终得到就是只出现过一次的两个数(其他在该位为 1 或 0 的数必然出现 0/2 次对异或结果无影响)
例: **a,b,a,b,c,d,e,f,e,f ** 分组后 A组:a, a , b, b, c 异或得到 c B组:e, e, f, f, d 异或得到 d
那么我们应该怎么借助分组位进行分组呢? 我们处理 c , d 的异或值,可以仅保留异或值的分组位 ,其余位变为 0 ,例如 101 变成 001或 100 为什么要这么做呢? 在第二题提到,我们可以根据 a & 1 来判断 a 的最后一位为 0 还是为 1,所以我们将 101 变成 001 之后,然后数组内的元素 x & 001 即可对 x 进行分组 。同样也可以 x & 100 进行分组. 那么我们如何才能仅保留分组位,其余位变为 0 呢?例 101 变为 001 ,我们可以利用 x & (-x) 来保留最右边的 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public int [] singleNumber(int [] nums) { int xorsum = 0 ; for (int num : nums) { xorsum ^= num; } int lsb = (xorsum == Integer.MIN_VALUE ? xorsum : xorsum & (-xorsum)); int type1 = 0 , type2 = 0 ; for (int num : nums) { if ((num & lsb) != 0 ) { type1 ^= num; } else { type2 ^= num; } } return new int []{type1, type2}; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { / / 思路:排序 / / [9 ,6 ,4 ,2 ,3 ,5 ,7 ,0 ,1 ] / / [0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,9 ] public int missingNumberBySort(int [] nums) { Arrays.sort(nums); for (int i= 0 ;i< nums.length;i+ + ){ if(i!= nums[i])return i; } return nums.length; } / / 异或 public int missingNumber(int [] nums) { int ret = nums.length; for (int i= 0 ;i< nums.length;i+ + ){ ret^ = (i^ nums[i]); } return ret; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 import java.util.Scanner;public class Main { public long ipAddress2int (String ipAddress) { String[] strings = ipAddress.split("\\." ); StringBuilder sb = new StringBuilder (); for (String s : strings) { Integer of = Integer.valueOf(s); StringBuilder sba = new StringBuilder (); while (of > 0 ) { int binary = of % 2 ; of = of >> 1 ; sba.append(binary); } while (sba.length() < 8 ) sba.append(0 ); sba.reverse(); sb.append(sba); } long ret = 0 ; for (int i = sb.length() - 1 ; i >= 0 ; i--) { int num = sb.charAt(i) - '0' ; ret += (num * Math.pow(2 , 31 - i)); } return ret; } public String int2IpAddress (Long num) { StringBuilder sba = new StringBuilder (); while (num > 0 ) { long binary = num % 2 ; num = num >> 1 ; sba.append(binary); } while (sba.length() < 32 ) sba.append(0 ); sba.reverse(); StringBuilder sb = new StringBuilder (); for (int i = 1 ; i <= 4 ; i++) { int ret = 0 ; for (int j = i * 8 - 1 ; j >= (i-1 )*8 ; j--) { int n = sba.charAt(j) - '0' ; ret += (n * Math.pow(2 , (i * 8 - 1 ) - j)); } sb.append(ret); if (i!=4 )sb.append("." ); } return sb.toString(); } public static void main (String[] args) { try (Scanner scanner = new Scanner (System.in)) { while (scanner.hasNext()) { String ipAddress = scanner.nextLine(); Long number = Long.valueOf(scanner.nextLine()); System.out.println(new Main ().ipAddress2int(ipAddress)); System.out.println(new Main ().int2IpAddress(number)); } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public int countPrimeSetBits(int left , int right ) { int ret = 0 ; while(left <= right ){ / / 1. 获取left 二进制中1 的个数 int num = left ; int sit = 0 ; while(num> 0 ){ sit+ = num& 1 ; num>> = 1 ; } / / 2. 判断是否是质数 if(isPrimeNumber(sit))ret+ + ; left + + ; } return ret; } public boolean isPrimeNumber(int num){ if(num= = 2 )return true ; if(num< 2 || num% 2 = = 0 )return false ; for (int i= 3 ;i<= Math.sqrt (num);i+ = 2 ){ if(num% i= = 0 )return false ; } return true ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public int [] smallestSubarrays(int [] nums) { int n = nums.length; int [] dp = new int [32 ]; int [] ret = new int [n]; for (int i = n - 1 ;i>=0 ;i--){ int dist = 1 ; for (int j=31 ;j>=0 ;j--){ if ((nums[i]&1 )==1 ){ dp[j] = i; } else if (dp[j]>0 ){ dist = Math.max(dp[j] - i + 1 ,dist); } nums[i]>>=1 ; } ret[i] = dist; } return ret; } }
相关资料