【剑指offer|图解|位运算】位1的个数+加密运算


📋前言

🌈 博客主页:@聆风吟的个人主页

🔥系列专栏:本期文章收录在《剑指offer每日一练》,大家有兴趣可以浏览和关注,后面将会有更多精彩内容!

📝作者留言:文章创作不易,可能会有些地方出现错误,还希望广大读者们能够帮忙指出,让我们大家一起共同进步。

☁️祝福语:祝大家国庆节快乐,学业有成,人人都能拿到一个好offer。

一. ⛳️位1的个数(题目难度:简单)

⌈ 在线OJ链接,可以转至此处自行练习 ⌋

题目:
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

示例:

输入: n = 11 (控制台输入 00000000000000000000000000001011)
输出: 3
解释: 输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。

限制:

输入必须是长度为 32 的 二进制串 。

解题思路一:
逐位判断:

  • 知识拓展: 根据 与运算 定义,设二进制数字 n,则有:
    • n&1 = 0,则二进制的 最后一位0
    • n&1 = 1,则二进制的 最后一位1

在这里插入图片描述
根据以上特点,考虑以下循环判断 :

  1. 判断 n 最右一位是否为 1,根据结果计数。
  2. 将 n 右移一位(本题要求把数字 n 看作无符号数,使用右移左端补零,对结果不会产生影响影响结果)。
    在这里插入图片描述

c++代码:

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int count = 0;//计数器,记录 1 出现的个数
        while(n){
            count += n & 1;//判断n的最后一位,如果为1计数器+1,否则计数器加+0
            n >>= 1;//右移一位
        }
        return count;
    }
};

解题思路二:
巧用n&(n-1):

  • (n−1) 解析: 二进制数字 n 最右边的 1 变成 0,并且此 1 右边的 0 全为 1。
  • n*(n-1) 解析:二进制数字 n 最右边的 1 变成 0,其余不变。

在这里插入图片描述
由上面的解析可得,使用一次可以将 n 的二进制中的一个 1 变为 0。因此,可以使用while循环每次判断 n 是否为 0,如果 n 不为 0让计数器+1并调用公式n&(n-1)将其结果赋给n,继续判断 n 的值;如果 n 为 0,返回计数器的值。
c++代码:

class Solution {
public:
    int hammingWeight(uint32_t n) {  
        int count = 0;
        while(n){
            count++;
            n &= (n-1);
        }
        return count;
    }
};

二. ⛳️加密运算(题目难度:简单)

⌈ 在线OJ链接,可以转至此处自行练习 ⌋

题目:
计算机安全专家正在开发一款高度安全的加密通信软件,需要在进行数据传输时对数据进行加密和解密操作。假定 dataA 和 dataB 分别为随机抽样的两次通信的数据量:

  • 正数为发送量
  • 负数为接受量
  • 0 为数据遗失

请不使用四则运算符的情况下实现一个函数计算两次通信的数据量之和(三种情况均需被统计),以确保在数据传输过程中的高安全性和保密性。

示例:

输入: dataA = 5, dataB = -1
输出: 4

限制:

  1. dataA 和 dataB 均可能是负数或 0
  2. 结果不会溢出 32 位整数

解题思路:

知识拓展:
    无进位和异或运算 规律相同,进位与运算 规律相同(并需左移一位)。

在这里插入图片描述
由以上可以得出:(和 s ) = (非进位和 n) + (进位 c),即可将 s = dataA + dataB 转化为:s = dataA + dataB ⇒ s = n + c。通过循环求出 n 和 c 后,将 n 和 c 分别看作dataA 和 dataB继续循环求 n 和 c,直到进位 c = 0 时,此时s = n,返回 n 即可。

知识拓展:
    在计算机系统中,数值一律用 补码 来表示和存储。补码的优势: 加法、减法可以统一处理(CPU只有加法器)。因此,以上方法同时适用于正数和负数的加法 。

c++代码:

class Solution {
public:
    int encryptionCalculate(int dataA, int dataB) {
        int c = 0; //进位和
        int n = 0; //无进位和

        while(dataB){
            c = (dataA & dataB) << 1;
            n = dataA ^ dataB;
            dataA = n;
            dataB = c;
        }

        return dataA;

    }
};

结尾

    今天的内容就到这里了,你们都学会了吗?如果还有疑问的话请在评论区里多多提问,大家可以一起帮你解决,让我们共同进步。创作不易,如果对你有用的的话点个赞支持下作者,你们的支持是作者创作最大的动力。关注我不迷路。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

聆风吟_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值