二进制

96 阅读1分钟

1. 只出现一次的数字

// leetcode 136 出现两遍的数都会异或成0,0和一次出现的数异或得到该数
class Solution {    
    public int singleNumber(int[] nums) {        
        // Map<Integer,Integer> map = new HashMap<>();        
        // for(int i=0; i<nums.length; i++){        
        //     Integer value = map.get(nums[i]);        
        //     if(value == null){        
        //         map.put(nums[i],1);        
        //     }else{        
        //         map.put(nums[i],value+1);        
        //     }        
        // }        
        // for(int key: map.keySet()){        
        //     if(map.get(key) == 1){        
        //         return key;        
        //     }        
        // }        
        // return 0;        
        int result = 0;        
        for(int i=0; i<nums.length; i++){            
            result = result^nums[i];        
        }        
        return result;    
        }
}
//  任何数和0做异或, 结果仍为原来的数,即:a^0 = 0^a = a
//  任何数和其自身做异或,结果为0,即:a^a=0
// 异或运算满足交换率和结合律,即:a^b^a = b^a^a = b^(a^a) = b^0 = b

2. 只出现一次的数字II

// leetcode 137
class Solution {    public int singleNumber(int[] nums) {        // 3(a+b+c)-(a+a+a+b+b+b+c) = 2c        long all_sum = 0;        Set<Long> set = new HashSet<Long>();        for(int i=0; i<nums.length; i++){            set.add((long)nums[i]);            all_sum += nums[i];        }        long element_sum = 0;        for(Long value : set){            element_sum += value;        }        return (int)((3*element_sum-all_sum)/2);    }}

3. 只出现一次的数字III

// leetcode 260  注释里面的是方法一
class Solution {    public int[] singleNumber(int[] nums) {        // Map<Integer,Integer> map = new HashMap<>();        // for(int num:nums){        //     int value = map.getOrDefault(num,0)+1;        //     map.put(num, value);        // }        // int[] result = new int[2];        // int index = 0;        // for(int key:map.keySet()){        //     if(map.get(key) == 1){        //         result[index] = key;        //         index++;        //     }        // }        // return result;        int temp = 0;        for(int num:nums){            temp ^= num;        }        // divide = 1, divide 一直往左移,找到temp第一位不为0的数        int divide = 1;        while((divide & temp) ==0){            divide <<= 1;        }        int a = 0, b=0;        for(int num: nums){            if((num & divide) != 0){                a ^= num;            }else{                b ^= num;            }        }        return new int[]{a,b};    }}

4. 位1的个数

// leetcode 191
public class Solution {    // you need to treat n as an unsigned value    public int hammingWeight(int n) {        int result = 0;        int i = 0;        int op = 1;        while(i<32){            if((op & n) != 0){                result++;            }            op <<= 1;            i++;        }        return result;    }}

5.  比特位计数

// leetcode 338
class Solution {    public int[] countBits(int num) {        int[] result = new int[num+1];        for(int i=0; i<=num; i++){            result[i] = oneNum(i);        }        return result;    }    private int oneNum(int n){        int result = 0;        int i = 0;        int op = 1;        while(i<32){            if((op & n) != 0){                result++;            }            op <<= 1;            i++;        }        return result;    }}

6. 颠倒二进制位

// leetcode 190public class Solution {    // you need treat n as an unsigned value    public int reverseBits(int n) {        int result = 0;        for(int i=0; i<32; i++){            // n 右移i位,然后和1做与运算,解析出该位是0还是1            int t = (n>>i) & 1;            if(t==1){                int move_step = 31 - i;                // 把刚才解析出来的 1 左移 move_step 位,然后做或运算                int temp = 1 << move_step;                result |= temp;            }        }        return result;    }}