java 几个位运算

456 阅读1分钟

labuladong的算法小抄 ;本文只用于自我梳理,原链如上

[TOC]

一、字母转换大小写、大小写逆转(位运算)

转小写 char |=' '; 转大写 char &= '_';大小写逆转 char ^=' ';

给定字符串:zHaNSanKoiNIAHoinoiSAIODoijoIni

结果输出:

// 大小写需要 逆转 的
reverse:ZhAnsANkOIniahOINOIsaiodOIJOiNI
// 全大写
toUpperCase:ZHANSANKOINIAHOINOISAIODOIJOINI
// 全小写
toLowerCase:zhansankoiniahoinoisaiodoijoini

代码示例:

/**
 * 转小写  char |=' ';
 * 转大写 char &= '_';
 * 大小写逆转 char ^=' ';
 */
@Test
public void testY() {
    String s = "zHaNSanKoiNIAHoinoiSAIODoijoIni";
    char[] result = new char[s.length()];
    int i=0;
    for(char tmp : s.toCharArray()) {
        tmp ^= ' ';
        result[i++] = tmp;
    }
    System.out.println("reverse:" + new String(result));

    i = 0;
    for(char tmp : s.toCharArray()) {
        tmp &= '_';
        result[i++] = tmp;
    }
    System.out.println("toUpperCase:" + new String(result));


    i = 0;
    for(char tmp : s.toCharArray()) {
        tmp |= ' ';
        result[i++] = tmp;
    }
    System.out.println("toLowerCase:" + new String(result));
}

二、判断两数字是否异号(位运算)

x^y<0 异或(同为0,异为1,判断两数字是否异号,只需判断两数符号位异或结果是否为负)

注意事项:0补码表示只有一种,0既不是正数也不是负数,没有+0,-0;若强加判断,补码中0符号位为0,隶属正数

/**
 * 0 的两种情况
 */
@Test
public void testJudgeTwoNums() {
    int x = -0, y = 2, a = 0, b = -2;
    System.out.println((x^y)<0); // false
    System.out.println((a^b)<0); // true
}

三、不用临时变量交换两个数

int a = 1, b = 2;
a ^= b;
b ^= a;
a ^= b;

四、消除一个数二进制表示中最后一个1

n&(n-1)

  1. 计算汉明权重

    @Test
    public void hammingWeight() {
    int n = 8;
    int res = 0;
    while (n != 0) {
        n = n & (n - 1);
        res++;
    }
    System.out.println("res二进制表示中1的个数:" + res);
    }
    
  2. 判断一个数字是不是2的指数(2的指数二进制表示中只包含一个1)

    boolean isPowerOfTwo(int n) {
        if (n <= 0) return false;
        return (n & (n - 1)) == 0;
    }
    

五、查询只出现一次的元素

a ^ a = 0 ;a ^ 0 = a

//给定非空正数数组,除了某个元素只出现一次外,其余元素均出现两次,找出只出现一次的那个元素
int singleNumber(int[] nums) {
    int res = 0;
    for (int n : nums) {
        res ^= n;
    }
    return res;
}