《七月集训》(第十天)——位运算

前言

        欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
        今天是七月集训第十天:位运算🔥
在这里插入图片描述

一、练习题目

        面试题 16.01. 交换数字
        1342. 将数字变成 0 的操作次数
        476. 数字的补数
        2044. 统计按位或能得到最大值的子集数目

二、算法思路

  • 1、面试题 16.01. 交换数字:🔥利用异或的性质。
  • 2、1342. 将数字变成 0 的操作次数:🔥递归即可。
  • 3、476. 数字的补数:🔥 我们首先要做的就是找到num的最高位然后左移一位减一得到num现有位都为1的数字,比如5 : 101 ,最高位为:100 ,左移一位减一得到 111。
  • 4、2044. 统计按位或能得到最大值的子集数目:🔥🔥记 n 是数组 nums 的长度,数组中的每个元素都可以选取或者不选取,因此数组的非空子集数目一共有 (2^n-1) 个。可以用一个长度为 n 比特的整数来表示不同的子集,在整数的二进制表示中,n 个比特的值代表了对数组不同元素的取舍。第 i 位值为1则表示该子集选取对应元素,第 i 位值为0则表示该子集不选取对应元素。求出每个子集的按位或的值,并计算取到最大值时的子集个数。

三、源码剖析

// 面试题 16.01. 交换数字
class Solution {
public:
    vector<int> swapNumbers(vector<int>& numbers) {
        numbers[0] = numbers[0] ^ numbers[1]; //(1)
        numbers[1] = numbers[0] ^ numbers[1]; //(2)
        numbers[0] = numbers[0] ^ numbers[1]; //(3)
        return numbers;
    }
};
  • 1、这里指的是 a = a ^ b;
  • 2、这里指的是b = a ^ b ^ b = a,也就是说numbes[1] = numbers[0]了;
  • 3、这里指的是a = a ^ b ^ a = b。
// 1342. 将数字变成 0 的操作次数
class Solution {
public:
    int numberOfSteps(int num) {
        if(num == 0) {
            return 0;
        }
        if(num & 1) {
            return numberOfSteps(num - 1) + 1;
        } else {
            return numberOfSteps(num / 2) + 1;
        }
    }
};
  • 1、递归按照题目意思做。
// 476. 数字的补数
class Solution {
public:
    int findComplement(int num) {
        unsigned int k = 1;
        while(k < num) {
            k <<= 1; //(1)
        }
        if(k == num) { //(2)
            return k - 1;
        }
        return k - 1 - num; //(3)
    }
};
  • 1、找到一个k >= num,k是一个2次,例如5:101,大于等于它的k是1000;
  • 2、k如果等于num说明num也是一个2次幂函数,所以取反就是把k - 1;
  • 3、如果k大于num,就像1的例子5,我们只要把k-1-num即可求出。
// 2044. 统计按位或能得到最大值的子集数目
class Solution {
public:
    int countMaxOrSubsets(vector<int>& nums) {
        int n = nums.size();
        int state = 1 << n, max = 0, ans = 0;
        for (int i = 0; i < state; i++){
            int cur = 0;
            for (int j = 0; j < n; j++){
                if ((1 << j) & i){
                    cur |= nums[j];
                }
            }
            if (cur > max){
                    max = cur;
                    ans = 1;
                } else if (cur == max){
                    ans++;
                }
        }   
        return ans;
    }
};
  • 1、位运算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值