面试官,你再问我 Bit Operation 试试?
在面试环节中,面试官很喜欢问一些特别的题目,这些题目有着特殊的解法,如果回答的巧妙往往能在面试中加分。
在这些题目中,位操作(Bit Operation)就是极具魅力的一种。今天,吴师兄就来分享 LeetCode 上几道跟 Bit Operation 有关的题目。
题目一: 位 1 的个数
LeetCode上第 191 号问题:编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数。
该题比较简单,解法有挺多,有位移法、位操作法、查表法、二次查表法等方法。
观察一下 n 与 n-1 这两个数的二进制表示:对于 n-1 这个数的二进制来说,相对于 n 的二进制,它的最末位的一个 1 会变成 0,最末位一个 1 之后的 0 会全部变成 1,其它位相同不变。
比如 n = 8888,其二进制为 10001010111000
则 n - 1 = 8887 ,其二进制为 10001010110111
通过按位与操作后:n & (n-1) = 10001010110000
也就是说:通过 n&(n-1)这个操作,可以起到消除最后一个1的作用。
所以可以通过执行 n&(n-1) 操作来消除 n 末尾的 1 ,消除了多少次,就说明有多少个 1 。
代码如下:
class Solution {
public:
int hammingWeight(uint32_t n) {
int cnt = 0;
while(n > 0){
cnt++;
n = n & (n - 1);
}
return cnt;
}
};
题目二:2 的幂
LeetCode上第 231 号问题:给定一个整数,编写一个函数来判断它是否是 2 的幂次方。
首先,先来分析一下 2 的次方数的二进制写法:
表格
仔细观察,可以看出 2 的次方数都只有一个 1 ,剩下的都是 0 。根据这个特点,只需要每次判断最低位是否为 1 ,然后向右移位,最后统计 1 的个数即可判断是否是 2 的次方数。
代码很简单:
class Solution {
public:
bool isPowerOfTwo(int n) {
int cnt = 0;
while (n > 0) {
cnt += (n & 1);
n >>= 1;
}
return cnt == 1;
}
};
该题还有一种巧妙的解法。再观察上面的表格,如果一个数是 2 的次方数的话,那么它的二进数必然是最高位为1,其它都为 0 ,那么如果此时我们减 1 的话,则最高位会降一位,其余为 0 的位现在都为变为 1,那么我们把两数相与,就会得到 0。
比如 2 的 3 次方为 8,二进制位 1000 ,那么 8 - 1 = 7,其中 7 的二进制位 0111。
图 2
利用这个性质,只需一行代码就可以搞定。
class Solution {
public:
bool isPowerOfTwo(int n) {
return (n > 0) && (!(n & (n - 1)));
}
};
题目三:数字范围按位与
LeetCode上第 201 号问题:给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
示例 :
输入: [26,30]
输出: 24
首先,将 [ 26 , 30 ] 的范围数字用二进制表示出来:
11010 11011 11100 11101 11110
而输出 24 的二进制是 11000 。
可以发现,只要找到二进制的 左边公共部分 即可。
所以,可以先建立一个 32 位都是 1 的 mask,然后每次向左移一位,比较 m 和 n 是否相同,不同再继续左移一位,直至相同,然后把 m 和 mask 相与就是最终结果。
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int d = INT_MAX;
while ((m & d) != (n & d)) {
d <<= 1;
}
return m & d;
}
};
题目四:重复的 DNA 序列
LeetCode上第 187 号问题:所有 DNA 由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。
编写一个函数来查找 DNA 分子中所有出现超过一次的 10 个字母长的序列(子串)。
示例:
输入: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
输出: ["AAAAACCCCC", "CCCCCAAAAA"]
首先,依旧先将 A , C , G , T 的 ASCII 码用二进制来表示:
A: 0100 0001 C: 0100 0011 G: 0100 0111 T: 0101 0100
通过观察发现每个字符的后三位都不相同,因此可以用末尾的三位来区分这四个字符。
题目要求是查找 10 个字母长的序列,这里我们将每个字符用三位来区分的话,10 个字符就需要 30 位 ,在32位机上也 OK 。
为了提取出后 30 位,需要使用 mask ,取值为 0x7ffffff(二进制表示含有 27 个 1) ,先用此 mask 可取出整个序列的后 27 位,然后再向左平移三位可取出 10 个字母长的序列 ( 30 位)。
为了保存子串的频率,这里使用哈希表。
首先当取出第十个字符时,将其存在哈希表里,和该字符串出现频率映射,之后每向左移三位替换一个字符,查找新字符串在哈希表里出现次数,如果之前刚好出现过一次,则将当前字符串存入返回值的数组并将其出现次数加一,如果从未出现过,则将其映射到 1。
举个
面试官,你再问我 Bit Operation 试试?的更多相关文章
- Java面试官最爱问的volatile关键字
在Java的面试当中,面试官最爱问的就是volatile关键字相关的问题.经过多次面试之后,你是否思考过,为什么他们那么爱问volatile关键字相关的问题?而对于你,如果作为面试官,是否也会考虑采用 ...
- 拜托!面试请不要再问我Spring Cloud底层原理[z]
[z]https://juejin.im/post/5be13b83f265da6116393fc7 拜托!面试请不要再问我Spring Cloud底层原理 欢迎关注微信公众号:石杉的架构笔记(id: ...
- 基础面试,为什么面试官总喜欢问String?
关于 Java String,这是面试的基础,但是还有很多童鞋不能说清楚,所以本文将简单而又透彻的说明一下那个让你迷惑的 String 在 Java 中,我们有两种方式创建一个字符串 String x ...
- 大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式)
大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式) 现在大部分的Spring项目都采用了基于注解的配置,采用了@Configuration 替换标签的做法.一 ...
- Java面试官最常问的volatile关键字
在Java相关的职位面试中,很多Java面试官都喜欢考察应聘者对Java并发的了解程度,以volatile关键字为切入点,往往会问到底,Java内存模型(JMM)和Java并发编程的一些特点都会被牵扯 ...
- 一线大厂面试官最喜欢问的15道Java多线程面试题
前言 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得更多职位,那么你应该准备很多关于多线程的问题. 他们会问面试者很多令人混淆的Java线程问题.面试官只是想确信面试者 ...
- 【测试工程师面试】在BOSS直聘上和面试官的一问一答
岗位描述: 信用卡核心系统功能测试,负责测试计划制定,测试设计,测试执行,测试进度掌控,自动化工具建设等工作.有责任心,执行力强,工作认真细致,逻辑思维强熟悉linux,oracle或者IBM大型机操 ...
- 面试官,别问我DNS了,也就这些!
提到网络,基本上都能把DNS给扯上去.为啥呢,今天我们来一探究竟. 1 Chrome浏览器原理 还记得面试过程中被问了千百遍的"输入URL后发生了什么"这个经典问题吗,因为这个问题 ...
- 面试官就是要问我SpringMVC的源码,差点顶不住!
<对线面试官>系列目前已经连载22篇啦!有深度风趣的系列! [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 & ...
随机推荐
- What is RandomCharacter.getRandomLowerCaseLetter() ?????
今天在看书顺便打打书上的代码时,看到这么一个方法的调用RandomCharacter.getRandomLowerCaseLetter()! 年轻的我看到这一大串单词时还以为是JDK自带类里面方法Or ...
- JavaBean转JSON方式
- js基础进阶--编码实用技巧(二)
我的个人博客:http://www.xiaolongwu.cn 接上篇文章 js编码的实用技巧(一) 5.合理利用||运算符 使用||可以作为参数之外的默认值,当第一个参数返回值为false时,那么第 ...
- virsh命令来创建虚拟机
virsh命令来创建虚拟机步骤 (1)生成硬盘镜像文件: 格式:raw或qcow2 # qemu-img create -f raw fdisk.img 10G qemu-img convert re ...
- cmd命令行下登陆备份导入导出msql数据
1.进入服务,找到mysql服务,在属性里找到mysql的安装路径 2.登陆 mysql -h 192.168.0.11 -P 3310 -u root -p 如果是访问的本机并且端口是默认的,那么 ...
- vi/vim的常用快捷键
vi/vim分为 命令模式,插入模式(编辑模式),末行模式(最后一行) 模式的转换 ① 其它模式==>正常模式 按 Esc键 ②正常模式==>插入模式 按 i 在光标前插入 按 I 在行首 ...
- CUDA编程模型之内存管理
CUDA编程模型假设系统是由一个主机和一个设备组成的,而且各自拥有独立的内存. 主机:CPU及其内存(主机内存),主机内存中的变量名以h_为前缀,主机代码按照ANSI C标准进行编写 设备:GPU及其 ...
- Centos7 下 tty2等文字窗口的中文乱码问题分析
在使用 tty 的时候遇到了一个事情,那就是主文件夹下面的中文文件是乱码: [备注]tty 是 通过 CTRL + ALT +F2~F6 获得的, 这与桌面系统中的终端不是一个概念, 望看到这篇 ...
- 使用Ratpack与Spring Boot构建高性能JVM微服务
在微服务天堂中Ratpack和Spring Boot是天造地设的一对.它们都是以开发者为中心的运行于JVM之上的web框架,侧重于生产率.效率以及轻量级部署.他们在服务程序的开发中带来了各自的好处.R ...
- php开启fileinfo扩展
1.检查当前环境: php -i|grep fileinfo 1 看是否已安装fileinfo扩展,若没有,则进行下一步. 2.安装fileinfo扩展 2.1.下载扩展包 根据各自的版本号进行下载 ...