|
| 1 | +package pp.arithmetic.leetcode; |
| 2 | + |
| 3 | +/** |
| 4 | + * Created by wangpeng on 2019-08-31. |
| 5 | + * 461. 汉明距离 |
| 6 | + * |
| 7 | + * 两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目。 |
| 8 | + * |
| 9 | + * 给出两个整数 x 和 y,计算它们之间的汉明距离。 |
| 10 | + * |
| 11 | + * 注意: |
| 12 | + * 0 ≤ x, y < 231. |
| 13 | + * |
| 14 | + * 示例: |
| 15 | + * |
| 16 | + * 输入: x = 1, y = 4 |
| 17 | + * |
| 18 | + * 输出: 2 |
| 19 | + * |
| 20 | + * 解释: |
| 21 | + * 1 (0 0 0 1) |
| 22 | + * 4 (0 1 0 0) |
| 23 | + * ↑ ↑ |
| 24 | + * |
| 25 | + * 上面的箭头指出了对应二进制位不同的位置。 |
| 26 | + * |
| 27 | + * 来源:力扣(LeetCode) |
| 28 | + * 链接:https://leetcode-cn.com/problems/hamming-distance |
| 29 | + * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 |
| 30 | + */ |
| 31 | +public class _461_hammingDistance { |
| 32 | + public static void main(String[] args) { |
| 33 | + _461_hammingDistance hammingDistance = new _461_hammingDistance(); |
| 34 | + System.out.println(hammingDistance.hammingDistance(1, 4)); |
| 35 | + System.out.println(hammingDistance.hammingDistance1(1, 254)); |
| 36 | + } |
| 37 | + |
| 38 | + /** |
| 39 | + * 解题思路: |
| 40 | + * 1.x^y做异或操作,得到的结果中不同位置都是1 |
| 41 | + * 2.将异或结果转换成二进制字符串 |
| 42 | + * 3.遍历二进制字符串得到 1 的个数 |
| 43 | + * |
| 44 | + * 更优解法{@link _461_hammingDistance#hammingDistance1(int, int)} |
| 45 | + * |
| 46 | + * @param x |
| 47 | + * @param y |
| 48 | + * @return |
| 49 | + */ |
| 50 | + public int hammingDistance(int x, int y) { |
| 51 | + int result = 0; |
| 52 | + int i = x ^ y; |
| 53 | + String s = Integer.toBinaryString(i); |
| 54 | + for (int j = 0; j < s.length(); j++) { |
| 55 | + if (s.charAt(j) == '1') result++; |
| 56 | + } |
| 57 | + return result; |
| 58 | + } |
| 59 | + |
| 60 | + /** |
| 61 | + * Integer.bitCount源码剖析 |
| 62 | + * (>>> 代表无符号右移,对于负数,右移后首位补0而非1) |
| 63 | + * 0x55555555 ==> 01010101010101010101010101010101 |
| 64 | + * 0x33333333 ==> 00110011001100110011001100110011 |
| 65 | + * 0x0f0f0f0f ==> 00001111000011110000111100001111 |
| 66 | + * |
| 67 | + * //第一步,每两位一个二进制数,每个二进制数的值表示这两位中“1”的数量。00->00,01->01,10->01,11->10 |
| 68 | + * i = i - ((i >>> 1) & 0x55555555); |
| 69 | + * //第二步,两两分组,计算出两两的总数,保存在4中 |
| 70 | + * i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); |
| 71 | + * //第三步,四四分组,计算出四四中的总数,保存在8中 |
| 72 | + * i = (i + (i >>> 4)) & 0x0f0f0f0f; |
| 73 | + * //第四步,八八分组,计算出八八中的总数,保存在16中 |
| 74 | + * i = i + (i >>> 8); |
| 75 | + * //第五步,16-16分组,计算出16-16总数 |
| 76 | + * i = i + (i >>> 16); |
| 77 | + * //结果返回 |
| 78 | + * return i & 0x3f; |
| 79 | + * |
| 80 | + * 过程并不是很好理解,可以通过debug和手写模拟下 |
| 81 | + * 用一句话就是把二进制数按两位分组,相邻分组两两相加得四位二进制的bitCount,再按四位分组,相邻分组两两相得八位二进制的bitCount,以此类推直到算出32位的bitCount数量。 |
| 82 | + * |
| 83 | + * @param x |
| 84 | + * @param y |
| 85 | + * @return |
| 86 | + */ |
| 87 | + public int hammingDistance1(int x, int y) { |
| 88 | + return Integer.bitCount(x ^ y); |
| 89 | + } |
| 90 | +} |
0 commit comments