【七月算法】day10 位运算

面试题 16.01. 交换数字

题目描述:

编写一个函数,不用临时变量,直接交换numbers = [a, b]ab的值。

思路:

看注释

class Solution {
public:
    vector<int> swapNumbers(vector<int>& numbers) {
        numbers[0] = numbers[0] ^ numbers[1];
        numbers[1] = numbers[0] ^ numbers[1]; // (numbers[0] ^ numbers[1]) ^ numbers[1] = numbers[0]
        numbers[0] = numbers[0] ^ numbers[1]; // (numbers[0] ^ numbers[1]) ^ numbers[1] = numbers[0] 
        return numbers;


    }
};

1342. 将数字变成 0 的操作次数

题目描述:

给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。

思路:

这个题之前做过的,用的非递归方法;

可以用递归,出口就是num为0时操作步数为0;

不用递归,就是普通算;

class Solution {
public:
    int numberOfSteps(int num) {
        if (num == 0) {
            return 0;
        }
        if (num & 1) {
            return numberOfSteps(num-1) + 1;
        }
        return numberOfSteps(num/2) + 1;
        
        // int cnt = 0;
        // while(num) {
        //     if (num % 2) num = num - 1;
        //     else num = num / 2;
        //     cnt ++;
        // }
        // return cnt;

    }
};

476. 数字的补数

题目描述:

对整数的二进制表示取反(0 变 1 ,1 变 0)后,再转换为十进制表示,可以得到这个整数的补数。

例如,整数 5 的二进制表示是 "101" ,取反后得到 "010" ,再转回十进制表示得到补数 2 。
给你一个整数 num ,输出它的补数。

思路:

先找到大于等于num的最小k,如果k与num相等(此时num为0或者是1后面跟若干0),那么结果就是(若干个0变成1)即k-1;否则结果就是k-1-num;

接下来用二进制位表示:

比如:num = 1000000, 那么k>=num的值就是 k=1000000。此时num==k,结果就是后面的六个0全变成1,即ans= 111111,k-1;

num = 1001001,那么k>=num的值就是 k=10000000。此时num<k,先把k后面的7个0全变成1,即k-1= 1111111,此时的结果为ans = (k-1)-num,即110110;

class Solution {
public:
    int findComplement(int num) {
        unsigned int k = 1; //2^31
        while (num > k) {
            k <<= 1;
        }
        if (num == k) {
            return k - 1;
        }
        return k - 1 - num;

    }
};

2044. 统计按位或能得到最大值的子集数目

题目描述:

给你一个整数数组 nums ,请你找出 nums 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。

如果数组 a 可以由数组 b 删除一些元素(或不删除)得到,则认为数组 a 是数组 b 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。

对数组 a 执行 按位或 ,结果等于 a[0] OR a[1] OR ... OR a[a.length - 1](下标从 0 开始)。

思路:

位或:两个二进制位有一个为1则结果为1;

数字的范围最多只有16,所以子集的数目最多有2的16次幂;
每个子集就是表示这个数取或者不取,所以正好可以用一个二进制位来对应,二进制位为1表示取,为0表示不取;
枚举所有的子集,计算子集的位或值,然后取最大的那个,当有取值相同时,计数器累加,最后返回计数器的值即可

class Solution {
public:
    int countMaxOrSubsets(vector<int>& nums) {
        int maxv = -1, maxc = 0;
        int n = nums.size();
        for (int i = 0; i < (1 << n) ; ++ i) {
            int ans = 0;
            for (int j = 0; j < n; ++ j) {
                if (i & (1 << j)) {
                    ans |= nums[j];
                }   
            }
            if (ans > maxv) {
                maxv = ans;
                maxc = 1;
            }else if (ans == maxv) {
                maxc ++;
            }
        }
        return maxc;
    }
};

猜你喜欢

转载自blog.csdn.net/ilovejujube/article/details/125701680
今日推荐