文章目录
1.LeetCode:面试题 16.01. 交换数字
编写一个函数,不用临时变量,直接交换numbers = [a, b]中a与b的值。
示例:
输入: numbers = [1,2]
输出: [2,1]
提示:
numbers.length == 2
-2147483647 <= numbers[i] <= 2147483647
老经典的题了,不适用中间变量把这两个数异或三次即可,比如a,b , 第一次异或后a= a^b, 第二次异或后 b=a ^ b ^ b=a ,最后一次异或 a= a ^ b ^ a =b;
class Solution {
public:
vector<int> swapNumbers(vector<int>& numbers) {
numbers[0]^=numbers[1];
numbers[1]^=numbers[0];
numbers[0]^=numbers[1];
return numbers;
}
};
2.LeetCode:1342. 将数字变成 0 的操作次数
给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。
示例 1:
输入:num = 14
输出:6
示例 2:
输入:num = 8
输出:4
示例 3:
输入:num = 123
输出:12
提示:
0 <= num <= 10^6
这道题的做法真的是很多很多很多,可以模拟,可以遍历,可以递归,可以用各种位运算技巧来做。这里就介绍一种简单易于理解的位运算的方法。
根据规则我们知道,当num最后一位为1也就是奇数需要减去他,如果是偶数右移一位相当于除2,这代表什么意思呢?这个规则的意义就是把num中的每一个1要右移到最后一位来减一消除他,所以答案就很明确了:num中1的个数加num最高位1的位置
class Solution {
public:
int getloc(int num)
{
for(int i=31;i>=0;i--)
{
if((num>>i)&1)
{
return i;
}
}
return -1;
}
int getcnt(int num)
{
int ans=0;
for(int i=31;i>=0;i--)
{
if((num>>i)&1)
{
ans++;
}
}
return ans;
}
int numberOfSteps(int num) {
int ans=0;
return max(getloc(num)+getcnt(num),0);
}
};
3.LeetCode:476. 数字的补数
对整数的二进制表示取反(0 变 1 ,1 变 0)后,再转换为十进制表示,可以得到这个整数的补数。
例如,整数 5 的二进制表示是 “101” ,取反后得到 “010” ,再转回十进制表示得到补数 2 。
给你一个整数 num ,输出它的补数。
示例 1:
输入:num = 5
输出:2
示例 2:
输入:num = 1
输出:0
提示:
1 <= num < 2^31
首先本题的取反并不是我们标准意义的取反,因为标准的取反是对所有位都取反而本题只是对num的现有位取反,所以我们首先要做的就是找到num的最高位然后左移一位减一得到num现有位都为1的数字,比如5 : 101 ,最高位为:100 ,左移一位减一得到 111.
那么有一种快速进行该操作的方法lowbit(),这个如果我们熟悉树状数组的话就很容易理解了,每次lowbit操作移除num的最后一位1的位置(并不是第几位二进制位而是一十进制数),那么我们可以利用该操作先记录该数字然后消除该位的1,直到num为0即可。
之后怎么办呢?每位取反相当于每位与1异或,所以这里异或即可。 这里记得转成longlong,当num位2147483647的时候左移一位会超int
class Solution {
public:
int findComplement(int num) {
int highbit=1;
int tmp=num;
while(tmp){
highbit=tmp&(-tmp);
tmp&=(tmp-1);
}
return (long long)num ^ ((long long)(highbit<<1)-1);
}
};
4.LeetCode:2044. 统计按位或能得到最大值的子集数目
给你一个整数数组 nums ,请你找出 nums 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。
如果数组 a 可以由数组 b 删除一些元素(或不删除)得到,则认为数组 a 是数组 b 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。
对数组 a 执行 按位或 ,结果等于 a[0] OR a[1] OR … OR a[a.length - 1](下标从 0 开始)。
示例 1:
输入:nums = [3,1]
输出:2
示例 2:
输入:nums = [2,2,2]
输出:7
示例 3:
输入:nums = [3,2,1,5]
输出:6
提示:
1 <= nums.length <= 16
1 <= nums[i] <= 1e5
观察数据n最大位16,立即想到了利用二进制枚举所有状态,每一位代表nums[i]选与不选,如果该位为1,那么结果或上该元素,吧所有状态都枚举过后,统计最大值出现的次数
class Solution {
public:
int countMaxOrSubsets(vector<int>& nums) {
int ans=0,cur=0,max=0;
int n=nums.size();
for(int i=0;i<(1<<n);i++){
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;
}
};