(位运算)北理工集训Day5

        第5天学习了位运算并做了一些相关的算法题目,接下来我将学习内容做以整理。

目录

1. 整型数据的存储

2. 字符型数据的存储

3. 位运算

4.相关算法题目

 题目:191. 位1的个数

代码实现

 题目338. 比特位计数

 代码实现

 题目342. 4的幂

 代码实现

题目405. 数字转换为十六进制数

 代码实现

题目 136. 只出现一次的数字       

 代码实现

题目268. 丢失的数字

代码实现 

题目389. 找不同

 代码实现

题目645. 错误的集合

 代码实现


1. 整型数据的存储

        (1) 存储形式:补码

        (2) 最高位:符号位01

        (3) 数据长度:2字节4字节

        (4) 取值范围:[-32 768,32 767] [-231,231-1]

下面以两个字节继续讨论:

        (5) 非负整数的原码、反码、补码相同

                10的原码、反码、补码为:

                        0000 0000 0000 1010

                最大非负整数的补码为:

                        0111 1111 1111 1111    (2的15次方-1)

                最小非负整数的补码为:

  0000 0000 0000 0000   (0)

        设想:

                最大非负整数的补码为:

                        1111 1111 1111 1111

                最小负整数的补码为:

                        1000 0000 0000 0000

        (6) 负数的原码、反码、补码不一样

          例如:

-10的原码为:

                  1000 0000 0000 1010

                  -10的反码:原码取反

                  1111 1111 1111 0101

                  -10的补码:反码+1

                  1111 1111 1111 0110

-1的补码:

  1111 1111 1111 1111 (-1)

  减去1,得到-2的补码:

  1111 1111 1111 1110

  -32767的补码:

  1000 0000 0000 0001

  减去1,得到-32768补码

  1000 0000 0000 0000  (-215)

        (7) 溢出

                  -32768-1 = 32767

                  1000 0000 0000 0000

                  0111 1111 1111 1111

                  32767+1 = -32768

                  0111 1111 1111 1111

                  1000 0000  0000 0000

 

2. 字符型数据的存储

        (1) 占用字节数:1字节

        (2) 存储形式:ASCII

                  例如:'A'的ASCII码为0100 0001

                             'a'的ASCII码为0110 0001

        (3) 字符和整数通用

                  'a'-32 == 'A'

3. 位运算

          指进行二进制位的运算。

          运算量:只能是整数字符

          运算规则:先将操作数转化为二进制数,然后按位运算符号位也必须按位运算

 (1) 与(&

位与运算规则:

整数与运算性质

位与运算规则:

  1 & 1 = 1

  1 & 0 = 0

  0 & 1 = 0

  0 & 0 = 0

  a & a = a

  a & 0 = 0

  0 & a = 0

  a & 1 = 1  或  0

  a & 0xf :  4位不变

   a^(a-1)  

 (2) 或(|

位或运算规则:

整数或性质

  1 | 1 = 1

  1 | 0 = 1

  0 | 1 = 1

  0 | 0 = 0

  a | a = a

  a | 0 = a

  0 | a = a

        例1a占一个字节,把a4位置0,高4位不变。

                  1111 0000  =  240

                  a & 0xf0

        例2a占一个字节,把a4位置1,高4位不变。

                  0000 1111  =  15

                  a | 0x0f

(3) 非(~

位非运算规则:

整数非性质:

  ~ 1 = 0

  ~ 0 = 1

  ~ 0 = -1

  ~ 5 = -6

          例如:计算~10

                  10的补码: 0000 1010

                          取反:1111 0101 (是负数)

负数补码到原码的算法:取反+1

         ​​​​​​​         1000 1010

           ​​​​​​​       1000 1011-11

规律:

(4) 异或(^

位异或运算规则:

整数异或性质:

  1 ^ 1 = 0

  1 ^ 0 = 1

  0 ^ 1 = 1

  0 ^ 0 = 0

  a ^ a = 0

  a & 0 = a

  0 & a = a

  a ^ b ^ c = a ^ c ^ b

        例3:交换两个整型变量的值。

          ​​​​​​​        a=a^b;

          ​​​​​​​        b=a^b;

          ​​​​​​​        a=a^b;

证明:

          a’=a^b

          b=a^b=(a^b)^b=a^(b^b)=a^0=a

          a=a^b=(a^b)^a=b^(a^a)=b^0=b

(5) 移位运算

          右移(>>)、左移(<<)

        例如:10<<1

                0000 1010

                0001 010020

特点:左移1位乘2右移1位除2

左移:一般移入10,按最高位确定

右移:一般移入0

注意:防止溢出

4.相关算法题目

 题目:191. 位1的个数

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

提示:

请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在上面的 示例 3 中,输入表示有符号整数 -3。

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

代码实现

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int res = 0;
        for(int i =0;i<32; ++i){
            res+=(n&1);
            n=n>>1;

        }

        return res;
    }
};

 题目338. 比特位计数

给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 ,计算其二进制数中的 1 的数目并将它们作为数组返回。

 代码实现

class Solution {
public:
    vector<int> countBits(int n) {
        int i=1;
        vector<int> ans(n+1);
        for(int i=0;i<=n;i++){
            if(i%2==0)
                ans[i]=ans[i/2];
            else
                ans[i]=ans[i/2]+1;
        }
        return ans;
    }
};

 题目342. 4的幂

        给定一个整数,写一个函数来判断它是否是 4 的幂次方。如果是,返回 true ;否则,返回 false 。

        整数 n 是 4 的幂次方需满足:存在整数 x 使得 n == 4的x次方

提示:   

 代码实现

class Solution {
public:
    bool isPowerOfFour(int n) {
        if(n<1) return false;
        if(n==1) return true;
        return(n%10==4||n%10==6)&&((n&-n)==n);
    }
};

题目405. 数字转换为十六进制数

        给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。

注意:

十六进制中所有字母(a-f)都必须是小写。
十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符'0'来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。 
给定的数确保在32位有符号整数范围内。
不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。

 代码实现

class Solution {
public:
    string toHex(int num) {
        string hex = "0123456789abcdef",ans="";
        if(num==0) return "0";
        for(int i=0;i<8&&num;i++){ //并且num不等于0
            ans=hex[num&15]+ans;
            num=num>>4;
        }
        return ans;
    }
};

题目 136. 只出现一次的数字       

        给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

        你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

 代码实现

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int res=0;
        for(int x:nums)
            res^=x;
        return res;

    }
};

题目268. 丢失的数字

        给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

进阶:

        你能否实现线性时间复杂度、仅使用额外常数空间的算法解决此问题?

代码实现 

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int res=0,y=1;
        for(int x:nums){
            res^=x^y++;
        }
            
        return res;

    }
};

题目389. 找不同

给定两个字符串 s 和 t,它们只包含小写字母。

字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。

请找出在 t 中被添加的字母。

 代码实现

class Solution {
public:
    char findTheDifference(string s, string t) {
        char res=0;
        for(char ch:s){
            res^=ch;

        }
        for(char ch:t){
            res^=ch;
        }
    return res;
    }
};

题目645. 错误的集合

        集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。

        给定一个数组 nums 代表了集合 S 发生错误后的结果。

        请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

 代码实现

class Solution {
public:
    vector<int> findErrorNums(vector<int>& nums) {
        //如果用unordered_set  可求和求差并找重复值 O(n)  O(n)
        vector<int> res;
        for(int i=0;i<nums.size();++i){
            int pos=abs(nums[i])-1;
            if(nums[pos]<0)
                res.push_back(pos+1);
            else
                nums[pos]*=-1;
        } 
        for(int i=0;i<nums.size();++i)
            if(nums[i]>0) res.push_back(i+1);
        return res;
    }
};

持续更新.....

♥♥♥每天提醒自己,自己就是个菜鸡!

♥♥♥已经看到最后啦,如果对您有帮助留下的每一个点赞、收藏、关注是对菜鸡创作的最大鼓励❀

♥♥♥有相关问题可以写在评论区,一起学习,一起进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

机器人spider

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

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

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

打赏作者

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

抵扣说明:

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

余额充值