【算法百题】专题五_位运算


前言

通过前面的学习,已经知道解一个题,首先从暴力解法入手,过程中尝试发现暴力解法的低效之处,和发现一些题目的规律(如滑动窗口题的指针单向移动性,二分题的二段性,前缀和题的目标可以用数学方法间接表示),从而着手优化:

在这里插入图片描述

首先我们需要补充一下一些位运算的预备知识:
在这里插入图片描述

位运算的规律是: 问题有二进制层面的特性


题目:

033. 判断字符是否唯⼀(easy)

分析

在这里插入图片描述

class Solution {
public:
    bool isUnique(string astr) {
        int bitmap = 0;
        for(auto cha : astr)
        {
            if(bitmap & (1 << (cha - 'a')))
            {
                return false;
            }
            bitmap |= (1 << (cha - 'a'));
        }
        return true;
    }
};

034. 丢失的数字(easy)

分析

在这里插入图片描述

//位运算
class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int ret = nums.size();
        for(int i = 0;i < nums.size();i++)
        {
            ret ^= i;
            ret ^= nums[i]; 
        }
        return ret;
    }
};
//空间复用
int missingNumber(vector<int>& nums) {
    int n = nums.size();
    for (int i = 0; i < n; i++) {
        while (nums[i] < n && nums[i] != i) {
            swap(nums[i], nums[nums[i]]);
        }
    }
    for (int i = 0; i < n; i++) {
        if (nums[i] != i) return i;
    }
    return n;
}

035. 两整数之和(medium)

分析

在这里插入图片描述

class Solution {
public:
    int getSum(int a, int b) {
        int x;
        while(b)
        {
            x = a ^ b;
            b = (a & b) << 1;        //二进制相加的进位和相&的值就差一个次方. 
            a = x;
        }
        return x;
    }
};

036. 只出现⼀次的数字 II(medium)

分析

在这里插入图片描述

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for(int i = 0;i < 32;i++)
        {
            int inum = 0;
            for(auto x:nums)
            {
                if((x >> i) & 1) inum++;
            }
            ret |= (inum % 3) << i;           //将我们某位个数余3赋值给ret的对应位.
        }
        return ret;
    }
};

037. 消失的两个数字(hard)

分析

在这里插入图片描述

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        int XOR = 0;
        for(auto x: nums)
        {
            XOR ^= x;
        }
        for(int i = 1; i <= nums.size() + 2; i++) XOR ^= i;
        
        int clf = XOR & -XOR;
        int XOR0 = 0;
        int XOR1 = 0;
        for(auto x: nums)
        {
            if(x & clf) XOR0 ^= x;
            else XOR1 ^= x;
        }
        for(int i = 1;i <= nums.size() + 2;i++)
        {
            if(i & clf) XOR0 ^= i;
            else XOR1 ^= i;
        }
        return {XOR0,XOR1};
    }
};

总结

位运算优化方向的规律感觉起来比较模糊,一些题目的思路方向清奇,但注意万变不离其宗(预备知识).


本文章为作者的笔记和心得记录,顺便进行知识分享,有任何错误请评论指点:)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值