Skip to content

Commit

Permalink
位运算
Browse files Browse the repository at this point in the history
  • Loading branch information
h2pl committed Apr 27, 2018
1 parent 9b64dac commit 7f4ee44
Show file tree
Hide file tree
Showing 14 changed files with 373 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/数据结构/位运算/一个数是否为4的n次方.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 一个数是否为4的n次方 {

public boolean isPowerOfFour(int num) {
if (num < 0) return false;
//保证这个数只有1个1并且1后面只有偶数个0,也就是1在奇数位上
if (Integer.bitCount(num) == 1 && Integer.numberOfTrailingZeros(num) % 2 == 0) {
return true;
}
return false;
}
}
19 changes: 19 additions & 0 deletions src/数据结构/位运算/一个数是否是2的n次方.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 一个数是否是2的n次方 {
//2的n次方的二进制表示只有1个1
public boolean isPowerOfTwo(int n) {
if (n < 0) return false;
if (Integer.bitCount(n) == 1) {
return true;
}return false;
}
// 利用 1000 & 0111 == 0 这种性质,得到以下解法:
//
// public boolean isPowerOfTwo(int n) {
// return n > 0 && (n & (n - 1)) == 0;
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 不用额外变量交换两个整数 {
public void swap (int a,int b) {
a = a ^ b;
b = b ^ a;
a = a ^ b;
}
}
46 changes: 46 additions & 0 deletions src/数据结构/位运算/位运算基础.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 位运算基础 {
// 位运算
//
//1. 基本原理
//
//0s 表示一串 0,1s 表示一串 1。
//
// x ^ 0s = x x & 0s = 0 x | 0s = x
// x ^ 1s = ~x x & 1s = x x | 1s = 1s
// x ^ x = 0 x & x = x x | x = x
// 利用 x ^ 1s = ~x 的特点,可以将位级表示翻转;利用 x ^ x = 0 的特点,可以将三个数中重复的两个数去除,只留下另一个数。
// 利用 x & 0s = 0 和 x & 1s = x 的特点,可以实现掩码操作。一个数 num 与 mask :00111100 进行位与操作,只保留 num 中与 mask 的 1 部分相对应的位。
// 利用 x | 0s = x 和 x | 1s = 1s 的特点,可以实现设值操作。一个数 num 与 mask:00111100 进行位或操作,将 num 中与 mask 的 1 部分相对应的位都设置为 1。
// 位与运算技巧:
//
// n&(n-1) 去除 n 的位级表示中最低的那一位。例如对于二进制表示 10110 100 ,减去 1 得到 10110011,这两个数相与得到 10110000。
// n-n&(~n+1) 去除 n 的位级表示中最高的那一位。
// n&(-n) 得到 n 的位级表示中最低的那一位。-n 得到 n 的反码加 1,对于二进制表示 10110 100 ,-n 得到 01001100,相与得到 00000100
// 移位运算:
//
// >> n 为算术右移,相当于除以 2n;
// >>> n 为无符号右移,左边会补上 0。
// << n 为算术左移,相当于乘以 2n。


// 2. mask 计算
//
// 要获取 111111111,将 0 取反即可,~0。
//
// 要得到只有第 i 位为 1 的 mask,将 1 向左移动 i-1 位即可,1<<(i-1) 。例如 1<<4 得到只有第 5 位为 1 的 mask :00010000。
//
// 要得到 1 到 i 位为 1 的 mask,1<<(i+1)-1 即可,例如将 1<<(4+1)-1 = 00010000-1 = 00001111。
//
// 要得到 1 到 i 位为 0 的 mask,只需将 1 到 i 位为 1 的 mask 取反,即 ~(1<<(i+1)-1)。

// 3. Java 中的位操作
//
// static int Integer.bitCount(); // 统计 1 的数量
// static int Integer.highestOneBit(); // 获得最高位
// static String toBinaryString(int i); // 转换为二进制表示的字符串
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package 数据结构.位运算;

import java.lang.reflect.Parameter;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 判断一个数的位级表示是否不会出现连续的0和1{
public boolean hasAlternatingBits(int n) {
while (n != 0) {
if (((n >> 1) & 1) == (n & 1)) {
return false;
}
n >>= 1;
}
return true;
}
}
28 changes: 28 additions & 0 deletions src/数据结构/位运算/字符串数组最大乘积.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 字符串数组最大乘积 {
public int maxProduct(String[] words) {
int n = words.length;
int[] val = new int[n];
//用一个二进制数来存储一个数所包含的字母种类。
//32位可以容纳26个字母,用数组保存n个二进制数,两两相与,如果结果为0
//说明这两个数没有重复的字母,可以返回。
for (int i = 0; i < n; i++) {
for (char c : words[i].toCharArray()) {
val[i] |= 1 << (c - 'a');
}
}
int ret = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if ((val[i] & val[j]) == 0) {
ret = Math.max(ret, words[i].length() * words[j].length());
}
}
}
return ret;
}
}
20 changes: 20 additions & 0 deletions src/数据结构/位运算/找出数组中缺失的那个数.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 找出数组中缺失的那个数 {
//和找唯一数一样的思路,数组中的数全部异或,再和1-n的所有数异或。
//最后的结果就是缺少的那个数
public int missingNumber(int[] nums) {
int n = nums.length;
int res = 0;
for (int i : nums) {
res = res ^ i;
}
for (int i = 0;i <= n;i ++) {
res = res ^ i;
}
return res;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 找到仅有的两个不重复的数 {
public int[] singleNumber(int[] nums) {
int res = 0;
for (int i : nums) {
res = res ^ i;
}
int []arr = new int[2];
//取到两个不同数异或结果的最右的1。比如0001000
res = res & (-res);
//两个数在这个位上1个为0一个为1,异或后分别得到两个数
for (int i : nums) {
if ((res & i) == 0) {
arr[0] ^= i;
}else {
arr[1] ^= i;
}
}
return arr;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 数组中唯一一个不重复的元素 {
public int singleNumber(int[] nums) {
int res = 0;
//相同的元素异或得0,0和唯一的一个元素异或得到该元素
for (int i : nums) {
res = res ^ i;
}
return res;
}
}
10 changes: 10 additions & 0 deletions src/数据结构/位运算/整数加法.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 整数加法 {
public int getSum(int a, int b) {
return b == 0 ? a : getSum((a ^ b), (a & b) << 1);
}
}
57 changes: 57 additions & 0 deletions src/数据结构/位运算/求一个数的补码.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 求一个数的补码 {


// ///题目描述:不考虑二进制表示中的首 0 部分。
//
// 对于 00000101,要求补码可以将它与 00000111 进行异或操作。那么问题就转换为求掩码 00000111。
//
// public int findComplement(int num) {
// if (num == 0) return 1;
// int mask = 1 << 30;
// while ((num & mask) == 0) mask >>= 1;
// mask = (mask << 1) - 1;
// return num ^ mask;
// }
// 可以利用 Java 的 Integer.highestOneBit() 方法来获得含有首 1 的数。
//
// public int findComplement(int num) {
// if (num == 0) return 1;
// int mask = Integer.highestOneBit(num);
// mask = (mask << 1) - 1;
// return num ^ mask;
// }
// 对于 10000000 这样的数要扩展成 11111111,可以利用以下方法:
//
// mask |= mask >> 1 11000000
// mask |= mask >> 2 11110000
// mask |= mask >> 4 11111111
// public int findComplement(int num) {
// int mask = num;
// mask |= mask >> 1;
// mask |= mask >> 2;
// mask |= mask >> 4;
// mask |= mask >> 8;
// mask |= mask >> 16;
// return (mask ^ num);
// }

public static void main(String[] args) {
findComplement(-1);
}
public static int findComplement(int num) {
if (num >= 0) return num;
int mask = 1;
mask = Integer.MIN_VALUE;
mask -= 1;
System.out.println(Integer.toBinaryString(num));
num = num ^ mask;
System.out.println(Integer.toBinaryString(mask));
System.out.println(Integer.toBinaryString(num));
return 1;
}
}
15 changes: 15 additions & 0 deletions src/数据结构/位运算/统计1到n二进制1的个数.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 统计1到n二进制1的个数 {
public int[] countBits(int num) {
int cnt = 0;
int []arr = new int[num + 1];
for (int i = 1;i <= num;i ++) {
arr[i] = Integer.bitCount(i);
}
return arr;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,79 @@
* Created by 周杰伦 on 2018/4/13.
*/
public class 统计两个数的二进制表示有多少位不同 {
//正确做法,使用异或
public int hammingDistance(int x, int y){
int z = x ^ y;
//异或的结果中,1所在的位就是x和y不同的位
int cnt = 0;
while (z != 0) {
//最高位是否为1
if ((z & 1) == 1) {
cnt ++;
//依次判断低位是否为1
}
z = z >> 1;
}
return cnt;
}
// 正确方法2
// 使用 z&(z-1) 去除 z 位级表示最低的那一位。
//
// public int hammingDistance(int x, int y) {
// int z = x ^ y;
// int cnt = 0;
// while (z != 0) {
// z &= (z - 1);
// cnt++;
// }
// return cnt;
// }
//
// 方法3 这个方法补错
// 可以使用 Integer.bitcount() 来统计 1 个的个数。
//
// public int hammingDistance(int x, int y) {
// return Integer.bitCount(x ^ y);


//错误做法,使用字符串比较
// public static int hammingDistance(int x, int y) {
// String s1 = Integer.toBinaryString(x);
// String s2 = Integer.toBinaryString(y);
// String temp;
// if (s1.length() >= s2.length()) {
// temp = s1;
// s1 = s2;
// s2 = temp;
// }
// System.out.println(s1);
// System.out.println(s2);
// int i = s1.length() - 1;
// int j = s2.length() - 1;
// int cnt = 0;
// while (i >= 0 && j >= 0) {
// if (s1.charAt(i) != s2.charAt(j)) {
// cnt ++;
// i --;
// j --;
// continue;
// }
// i --;
// j --;
// }
// while (j >= 0) {
// if (s2.charAt(j) == '1') {
// cnt ++;
// j --;
// continue;
// }
// j --;
//
// }
// return cnt;
// }
//
// public static void main(String[] args) {
// System.out.println(hammingDistance(3,1));
// }
}
17 changes: 17 additions & 0 deletions src/数据结构/位运算/翻转一个数的比特位.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package 数据结构.位运算;

/**
* Created by 周杰伦 on 2018/4/27.
*/
public class 翻转一个数的比特位 {
// you need treat n as an unsigned value
public int reverseBits(int n) {
int ret = 0;
for (int i = 0; i < 32; i++) {
ret <<= 1;
ret |= (n & 1);
n >>>= 1;
}
return ret;
}
}

0 comments on commit 7f4ee44

Please sign in to comment.