图解算法数据结构—习题记录 | 位运算

LCR 133. 位 1 的个数

思路:位运算知识 

位运算知识:

  • 移位操作
    • 右移>>:向右移动,左侧空位补0 <=> **向下整除2ⁿ
    • 左移>>:向左移动,右侧空位补0 <=> **乘以2ⁿ
  • 取余数 n%2 等价于 判断二进制最右位 n&1 (结果为1=>奇数)

 (分治法专题的LCR 134. Pow(x, n)也用到该知识点)

public class Solution
{
    public int HammingWeight(uint n)
    {
        int res = 0;
        while (n != 0)
        {
            if ((n & 1) == 1) res++;
            n >>= 1;
        }

        return res;
    }
}

LCR 190. 加密运算 ❌

思路:用位运算的知识模拟加法。

  1. n = 数a^数b:相当于把b的值分一部分到a上就形成了新的数n(1^1=0这里忽略了进位,所以第二步用&来模拟不会对结果造成影响)
  2. c = 数a&数b<<1:1&1=1,再左移一位(右补零)相当于记录两数相加的进位

以上两步循环直到b=0则相加完成。

(之后回头看,看不懂可以参考图解算法数据结构 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台

public class Solution
{
    public int EncryptionCalculate(int dataA, int dataB)
    {
        int n = 0, c = 0;
        while (dataB != 0)
        {
            n = dataA ^ dataB; //无进位和n => 该步骤相当于b的值分了一部分给a
            c = (dataA & dataB) << 1; //进位c => & + 左移 相当于进位操作
            // 循环运算
            dataB = c;
            dataA = n;
        }

        return dataA;
    }
}

LCR 177. 撞色搭配 ❌

思路:(看注释,方法来源图解算法数据结构 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台

public class Solution
{
    public int[] SockCollocation(int[] sockets)
    {
        int a = 0, b = 0, n = 0, m = 1;
        foreach (var num in sockets) // 遍历异或,找出不相同的两个编号(相同两个数异或=0,因此结果是出现一次的数字)
            n ^= num;

        while
            ((n & m) == 0) // 循环左移,计算m(两个只出现一次的数字为𝑥,𝑦,由于𝑥≠𝑦,则x和y二进制至少有一位不同(即分别为 0 和 1 ),循环 &+左移 结果==1可以找到第一个不同的位)
            m <<= 1;

        foreach (var num in sockets) // 根据m&的结果可以将sockets拆分为分别包含x和y的两个子数组。再分别对两子数组遍历执行异或操作,即可得到两个只出现一次的数字x,y。
        {
            if ((m & num) == 0)
                a ^= num;
            else
                b ^= num;
        }

        return new int[] { a, b };
    }
}

LCR 178. 训练计划 VI ❌

方法一:有限状态机(推荐使用,但暂时没看懂)

方法二:遍历统计(遍历数组,统计每个数的二进制位1出现的次数之和;对每位次数%3,得到的结果为“只出现一次的数字”的各二进制位;使用左移+或运算还原该数字并返回)

方法参考: 

public class Solution
{
    public int TrainingPlan(int[] actions)
    {
        int[] counts = new int[32];
        for (int i = 0; i < actions.Length; i++)
        {
            for (int j = 0; j < 32; j++)
            {
                counts[j] += actions[i] & 1; // 更新第 i 位 1 的个数之和
                actions[i] >>= 1;
            }
        }

        int res = 0;
        for (int i = 31; i >= 0; i--)
        {
            res <<= 1;
            res |= counts[i] % 3; // 恢复第 i 位
        }

        return res;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值