剑指offer(八):位运算

剑指offer(八):位运算

在这里插入图片描述

题目一:二进制中 1 的个数

方法一:逐位进行操作
public class Solution {
    public int hammingWeight(int n) {
        int res = 0;
        while(n != 0) {
            res += n & 1;
            //按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。
            n >>>= 1;
        }
        return res;
    }
}
方法二:n&(n-1)–精巧

在这里插入图片描述

public class Solution {
    public int hammingWeight(int n) {
        int res = 0;
        while(n != 0) {
            res++;
            n &= n - 1;
        }
        return res;
    }
}

题目二:数组中数字出现的次数

异或运重要性质:两个相同数字异或为 0 ,即对于任意整数 a⊕a=0 。因此,若将nums 中所有数字执行异或运算,留下的结果则为出现一次的数字 x。

public int[] singleNumber(int[] nums) {
    int x = 0;
    for(int num : nums)  // 1. 遍历 nums 执行异或运算
        x ^= num;
    return x;            // 2. 返回出现一次的数字 x
}
题目解法:

两个只出现一次的数字为 x, y,由于 x/y ,则 x和 y二进制至少有一位不同(即分别为 0和 1 )根据此位可以将 nums 拆分为分别包含 x和 y的两个子数组。

class Solution {
    public int[] singleNumbers(int[] nums) {
        int x = 0, y = 0, n = 0, m = 1;
        for(int num : nums)               // 1. 遍历异或
            n ^= num;
        //找出两个只出现一次的数的数位上不相等的位,根据这个将两个只出现一次的数分开
        while((n & m) == 0)               // 2. 循环左移,计算 m
            m <<= 1;
        for(int num: nums) {              // 3. 遍历 nums 分组
            if((num & m) != 0) x ^= num;  // 4. 当 num & m != 0
            else y ^= num;                // 4. 当 num & m == 0
        }
        return new int[] {x, y};          // 5. 返回出现一次的数字
    }
}

题目三:数组中数字出现的次数 II

**思想:**统计所有数字的各二进制位中 1的出现次数,并对3求余,结果则为只出现一次的数字

class Solution {
    public int singleNumber(int[] nums) {
        int[] counts = new int[32];
        for(int num : nums) {
            for(int i = 0; i < 32; i++) {
                counts[i] += num & 1; // 更新第 i 位 1 的个数之和
                num >>= 1;            // 第 i 位 --> 第 i 位
            }
        }
        int res = 0, m = 3;
        for(int i = 31; i >= 0; i--) {
            res <<= 1;
            res |= counts[i] % m;     // 恢复第 i 位
        }
        return res;
    }
}

题目四:不用加减乘除做加法

设两数字的二进制形式 a, b,求其和 s = a + b,a(i)代表 a 的二进制第 i位,则分为以下四种情况:
在这里插入图片描述

无进位和异或运算 规律相同,进位与运算 规律相同(并需左移一位)

class Solution {
    public int add(int a, int b) {
        //当进位为 0 时跳出
        while(b != 0) {
            int c = (a & b) << 1;  // c = 进位
            a ^= b; //非进位和
            b = c; //进位
        }
        return a;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值