前言
这是七月集训的第十日,今日的训练内容是 位运算
解题报告
第九日的内容比较难,想多做几天,先做一下比较简单的第十日。
1.力扣面试题 16.01. 交换数字
原题链接
题目概述
编写一个函数,不用临时变量,直接交换numbers = [a, b]中a与b的值。
解题思路
经典的互换方式,只要把代码拆开来写一下就可以看出来是怎么回事。
源码剖析
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* swapNumbers(int* numbers, int numbersSize, int* returnSize){
int i;
for(i=1;i<numbersSize;++i){
numbers[i]=numbers[i]^numbers[i-1];
numbers[i-1]=numbers[i]^numbers[i-1];
numbers[i]=numbers[i]^numbers[i-1];
}
*returnSize = numbersSize;
return numbers;
}
2.力扣1342
原题链接
题目概述
给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。
解题思路
按要求解题即可。
源码剖析
int numberOfSteps(int num){
int ans = 0;
while(num!=0){
if(num&1){
num-=1;
ans++;
}else{
num/=2;
ans++;
}
}
return ans;
}
3.力扣476
原题链接
题目概述
对整数的二进制表示取反(0 变 1 ,1 变 0)后,再转换为十进制表示,可以得到这个整数的补数。
例如,整数 5 的二进制表示是 “101” ,取反后得到 “010” ,再转回十进制表示得到补数 2 。
给你一个整数 num ,输出它的补数。
解题思路
首先先找到原来的 num 的位数,然后用相同位数的 1 去对原来的数字进行 ^ 操作即可。注意这里的 n 可能会超过最大值,所以只用 int
是不够的。
源码剖析
int findComplement(int num){
long n = 2;
while(n - 1 < num){
n <<= 1;
}
return (n - 1) ^ num;
}
4.力扣2044
原题链接
题目概述
给你一个整数数组 nums ,请你找出 nums 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。
如果数组 a 可以由数组 b 删除一些元素(或不删除)得到,则认为数组 a 是数组 b 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。
对数组 a 执行 按位或 ,结果等于 a[0] OR a[1] OR … OR a[a.length - 1](下标从 0 开始)。
解题思路
直接暴力枚举,并把符合条件的解记录进计数器,然后就可以得到答案了,这题貌似还可以使用DFS进行解题,先做记录。
源码剖析
int countMaxOrSubsets(int* nums, int numsSize){
int max = 0;
int ans = 0;
for (int i = 1; i < (1 << numsSize); i++) {
int tmp = 0;
for (int j = 0; j < numsSize; j++) {
if (i & (1 << j)) {
tmp |= nums[j];
}
}
if (tmp == max) {
ans++;
} else if (tmp > max) {
max = tmp;
ans = 1;
}
}
return ans;
}