关于位运算的一些小技巧

位运算在一些问题上总能发挥一些意想不到的优势,不过对于不是对其有一定理解的coder,位运算解决问题相对晦涩;

我按照使用功能上 为大家整理了一些技巧供大家参考,一般无须过多深究。

实用功能 三四五 ~~ 

一、将26个英文字符大写转小写,小写转大写,大小写互换。

     (1)大写转小写:        ('a' | ' ') = 'a' ;   ('A' | ' ') = 'a';

     (2)小写转大写:        ('a' & '_') = 'A' ;   ('A' & '_') = 'A';

     (3)大小写互换:        ('a' ^ ' ') = 'A' ;   ('A' ^ ' ') = 'a';

     这个用处不大,原理也很简单,就是ascii码经过对应的转换。

二、不使用第三个变量交换两个变量的值。

     int a = 1, b = 2;

     a = a ^ b    

     b = a ^ b    

     a = a ^ b

     // a, b = 2, 1

    这个方法实际用处好像也不大,面试可能会用到,与python中的 a, b = b, a 交换引用 都算解决的方式。

三、判断两个数是否异号

     int  x = -1, y = 2;

     bool f = ((x ^ y) < 0; //true

     int x = 1, y = 3;

     bool f = ((x ^ y) < 0; //false

     这一点对比常规判断方法还是比较方便的。比较推荐小伙伴们记下。

四、n & (n - 1)的用法。

     这个操作的作用是消除数字 n 的二进制表示中的最后一个 1。

     举个列子  n 的 二进制是 0 0 0 0  0 1 1 0 0 0  

                     n-1 之后变成   0 0 0 0  0 1 0 1 1 1    (上面的n 从低位到高位起 第一个不为0的数 借1,就有了下面这种情况,可以自己想一下)

                     按位与之后      0 0 0 0  0 1 0 0 0 0    (对比n发现消除了最后一个1)

     在明白作用之后 就衍生出了一些奇妙的用途。

     (1) 判断一个数是不是2的指数(都是大于0 的数)。

          因为如果一个数是2的指数的话,它的二进制表示就绝对是只有一个1 存在,例如 2 ** 3 == 8 (0000 0100),这也不难理解因为每一个位 都是2的指数。

          这样就可以直接使用 n & (n-1) 消除仅有的一个1,判断是否为0即可

          例如 16 & (16 - 1) == 0          // 16 == 2 ** 4

 

五、使用 ^(异或)判断一个数组中仅出现一次的数字(这个数字唯一,且其他数字出现偶次数)

       单独写这个用法是因为在leetcode上136题只出现一次的数字中  得到了充分应用~

       nums = [2,5,2,3,3,5,3,3,4,7,7]

       【Java】

  public static int singleNumber(int[] nums) {
         int num = 0;
         for (int i = 0; i < nums.length; i++) {
             num = num ^ nums[i];
         }
         return num;
     }

【Python】
return reduce(int.__xor__, nums)

相信一些同学在初期不太容易想到这样的方法,那么就算我们暂时没有这样的思路也要知其所以然,为什么异或可以实现。
因为异或运算存在一些规律,满足了交换律结合律
普通规律: x ^ 0 = x ;
x ^ x = 0 ;
结合律和交换律:
a ^ a ^ b ^ c ^ d ^ c ^ d == (a ^ a) ^ (c ^ c) ^ (d ^ d) ^ b == 0 ^ 0 ^ 0 ^ b == b


                     

猜你喜欢

转载自www.cnblogs.com/wikis/p/11321798.html