一、原题目链接
1.面试题 05.07. 配对交换
2.476. 数字的补数
3.191. 位1的个数
4.面试题 16.01. 交换数字
二、使用方法
面试题 05.07. 配对交换
交换数字的奇数偶数位
(位0与位1交换,位2与位3交换,以此类推)
例如:
输入2(10) 输出1(01)
输入14(1110) 输出13(1101)
方法:
0xaaaaaaaa=10101010101010101010101010101010
0x55555555=01010101010101010101010101010101
1.保留奇数位与偶数位分别储存
原数字分别与0xaaaaaaaa,0x55555555进行与&运算
2.偶数位向右移动一位,奇数位向左移动一位
(如果写在同一行需要注意的是移位>>/<<的运算先于与&运算,因此需要加括号)
3.奇数位偶数位合并
将得到的两个结果进行或|运算就是结果
代码:
var exchangeBits = function(num) {
let even=(num&0xaaaaaaaa)>>1;
let odd=(num&0x55555555)<<1;
return even|odd;
};
476. 数字的补数
输入正整数,输出它的补数。补数是对该数的二进制表示取反
例如:
输入13(1101) 输出2(0010)
输入9(1001 )输出6(0110)
方法:
这里我运用的是javascript,因为javascript的二进制特定是32位,因此使用否~运算最左位会变成符号位1,结果就会变为负数
这里运用的是异或^1运算
0^1=1
1^1=0
可以得知与1进行异或运算会使原位变成相反数字
将原数字转成2进制再遍历每一位分别进行异或^1运算,将结果加入字符串
代码:
var findComplement = function(num) {
let res='';
num=num.toString(2);
for(let i=0;i<num.length;i++){
res+=num[i]^1;
}
return parseInt(res,2)
};
191. 位1的个数
输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数
例如:
输入1101 输出3
输入1001 输出2
方法:根据布赖恩·克尼根算法
1.设置循环条件
直到n=0
2.算法规律
将n和n-1进行与&运算
例:
11011010 (n)
11011001 (n-1)
进行与&运算后
11011000
相当于去掉了尾数的1,因此只需要记录循环次数即可
代码:
var hammingWeight = function(n) {
let res=0;
while(n!=0){
n=n&(n-1);
res++;
}
return res;
};
面试题 16.01. 交换数字
编写一个函数,不用临时变量,直接交换numbers = [a, b]中a与b的值。
输入: numbers = [5,3]
输出: [3,5]
方法:利用异或运算
例如:
5=0101
3=0011
0101^0011=0110 存在number[0]
0110^0011=0101 存在number[1]
0110^0101=0011 存在number[0]
var swapNumbers = function(numbers) {
numbers[1]^=numbers[0];
numbers[0]^=numbers[1];
numbers[1]^=numbers[0];
return numbers;
};
总结
使用一些位运算的方法可以减少花费的时间