算法之位操作

一、基本操作

(1)异或即^:针对二进制,相同为0,不同为1

  1)交换律:a ^ b ^ c = a ^ c ^ b

  2)任何数与0异或为任何数 0 ^ n = n

(2)位与运算&:针对二进制每一位进行&操作,当都为1时才是1;

(3)或操作|:针对二进制,有1即为1

二、应用

(1)异或

//给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

class Solution {
    public int singleNumber(int[] nums) {
        int a=0;
        for(int i:nums){
            a^=i;
        }
        return a;
    }
}

(2)&与|

//给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
//思路:将每个数想象成32位的二进制,对于每一位的二进制的1和0累加
//起来必然是3N或者3N+1, 为3N代表目标值在这一位没贡献,3N+1
//代表目标值在这一位有贡献(=1),然后将所有有贡献的位|起来就是结
//果。这样做的好处是如果题目改成K个一样,只需要把代码改成cnt%k,
//很通用

class Solution {
    public int singleNumber(int[] nums) {
        int res=0,msak=1;
        for(int i=0;i<32;i++){
            msak=1<<i;
            int count=0;
            for(int j:nums){
                if((j&msak)!=0){
                    count++;
                }
            }
            if(count%3!=0){
                res|=msak;
            }
        }
        return res;
    }
}

(3)^与&

  题目:一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

  思路如下:

class Solution {
    public int[] singleNumbers(int[] nums) {
        int res=0;
        for(int i:nums){
            res^=i;
        }
        int h=1;
        while((h&res)==0){
            h<<=1;
        }
        int a=0,b=0;
        for(int i:nums){
            if((h&i)==0){
                a^=i;
            }else{
                b^=i;
            }
        }
        return new int[]{a,b};
    }
}

 

posted on 2020-04-29 11:25  hdc520  阅读(221)  评论(0)    收藏  举报

导航