开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情 这也是第37篇文章
前言
今天总结的主题是——位运算。
先来一道经典的题目
位1的个数
题目
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量。
思路
因为我是Java选手,知道在Java中有个Integer.bitCount(int num)的方法可以统计num的二进制形式中的1的个数。
不过在这道题中直接用这个方法肯定是不合适的,因为题目要考察的不是调用api的能力,而是实现api的能力。
用&和<<操作遍历每一位,不为0就计数+1。
代码实现
public class Solution {
public int hammingWeight(int n) {
int cnt=0;
for(int i=0;i<32;i++){
if((n&(1<<i))!=0) cnt++;
}
return cnt;
}
}
另一道很经典的题目
不用加减乘除做加法
题目
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号
思路
数字逻辑和计组课告诉我们,其实十进制的“+”、“-”、“*”、“/”都可以用二进制位运算来表示,机器实现上有各种补码加法器等等。
对加法而言,只要抓住两点:
- 当前位变成什么 异或^的性质是这个位的最佳描述
- 有没有进位 (对二进制加法而言,如果两个位都为1,就会有进位)
代码实现
class Solution {
public int add(int a, int b) {
int cur=b,carry=a;
while(carry!=0){
cur=a^b;
carry=a&b;
carry=carry<<1;
a=cur;
b=carry;
}
return cur;
}
}
这道题位运算的思想有点隐蔽。
只出现一次的数字
题目
给你一个 非空 整数数组
nums,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
思路
可以用异或^的性质,不同为1,相同为0。
代码实现
class Solution {
public int singleNumber(int[] nums) {
int res=0;
for(int num:nums){
res^=num;
}
return res;
}
}
颠倒二进制位
题目
颠倒给定的 32 位无符号整数的二进制位。
思路
可以新构造一个二进制数,从后往前遍历原二进制的位,将它逐个加到新的二进制数中。
代码实现
public class Solution {
// you need treat n as an unsigned value
public int reverseBits(int n) {
int res=0;
for(int i=32;i>0;i--){
res=res<<1;
res+=n&1;
n=n>>1;
}
return res;
}
}