移位和位运算相关算法题学习积累
最近逛博客发现几个很有意思的算法题,大都是二进制相关的移位和位运算相关的,为此我暂且归为一类来整理学习,这也为后续遇到同等问题可以提供解法和思路。
当前文章基于JDK 1.8进心学习和测试。
一、判断一个整数是偶数还是奇数
题目很简单,就是判断一个整数是偶数还是奇数,整数可能是负数、零和正数。
解法一:
1 public static boolean isEven(int num) { 2 return num % 2 == 0 ? true : false; 3 }
注意,这种简单的算法其实是有个陷阱的,你只能按照上面这种方式来使用,不能够用【num % 2 == 1】这种方式来判断奇数然后剩下的就是偶数的方式,因为在Java中,取模运算的规则是【A%B == A - (A / B) * B】,所以如果以取模判断奇数的话,那么输入-1的话,-1%2的结果却不是1,上面的等式就不成立,所以就会把-1误判为偶数,这样就错误了,所以这里提醒一下,不能使用模2的结果是否等于1来判断奇偶。
解法二:
因为奇数的二进制最后一位都是1,所以我们可以在此做文章,我们用1去与这个数,如果结果不是0,那就是奇数,否则为偶数,看下面代码:
1 public static boolean isEven(int num) { 2 return (num & 1) == 0 ? true : false; 3 }
二、输出该整数的二进制中1的个数
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
问题思路就是先从高位开始计算1的个数,然后把高位去掉,再计算剩余的,这里用与操作符,同1做&运算,最后剩下的是1。n&(n-1)的操作,能把n的最高位的1给去掉,以此来计数。
1 public static int countOne(int num) { 2 int count = 0; 3 while(num != 0) { 4 num &= (num - 1); 5 count++; 6 } 7 return count; 8 }
三、输出该整数的二进制中0的个数
与上面的问题相似,也是用移位来操作,先比较最末尾的数是否为0,判断完成之后再整体右移一位,比较方法是&1的结果是否为0,为0则统计结果。
1 public static int countZero(int num) { 2 int count = 0; 3 while(num != 0) { 4 if((num & 1) == 0) { 5 count++; 6 } 7 num >>>= 1; 8 } 9 return count; 10 }
四、判断一个整数是否是2的N次幂
这个题目也是当初我面试的时候遇到的,其实很简单,想一下2的N此幂的特征,就是1的N次左移位,在二进制数看来,这个数就是一个1后面带着一串0,很好处理,通过n&(n-1)的方式来处理,只要结果是0,那么此数就是2的N次幂。
1 public static boolean is2Power(int num) { 2 return (num & (num - 1)) == 0 ? true : false; 3 }
五、输出一个整数的二进制高位连续0的个数。
将一个整数的二进制数中,将其高位连续为0的个数,比如整数28,在计算机中的二进制存储为0000, 0000, 0000, 0000, 0000, 0000, 0001, 0010,那么高位连续为0的个数为27个,写一个程序,输入这样一个整数,能够输出该数的高位连续为0的个数长度,比如输入18结果为27。
解法一:
移位计数,每次向右移位之后然后看此数是否为0,如果是则说明前面都是0了,然后通过每次移位计数来统计0的个数。
1 public static int getZerosLen(int num) { 2 int size = Integer.SIZE; 3 int count = 1; 4 while((num >>>= 1) != 0) { 5 count++; 6 } 7 return size - count; 8 }
解法二:
上面这种方法可行,但是复杂度就是O(Size of Integer)的大小了,其实在Integer类中有个静态方法toBinaryString(int i),这个方法就是将整数转换为二进制,而其调用了一个内部函数toUnsignedString0(int val, int shift),这个函数有个numberOfLeadingZeros方法就是计算int变量的计算机二进制表示的高位连续0位的数量,我们可以通过这种方法来获得最高非0位到最高位的长度。
1 public static int getZerosLen(int num) { 2 if (num == 0) 3 return 32; 4 int n = 1; 5 if (num >>> 16 == 0) { n += 16; num <<= 16; } 6 if (num >>> 24 == 0) { n += 8; num <<= 8; } 7 if (num >>> 28 == 0) { n += 4; num <<= 4; } 8 if (num >>> 30 == 0) { n += 2; num <<= 2; } 9 n -= num >>> 31; 10 return n; 11 }
上面的代码也是通过移位,但是采用了分治思想,就是每次一半一半的移位,这也是得益于二进制数字的特性。先通过移动一半即右移16位再判断移动后数据是否等于0,为0的话说明高16位都是0,计数16,同时把低16位冲到高16位,即左移16位后面都补0,接着看高16位,同样采用分治法,先从一半开始看,16+16/2=24,移动14位再计算,以此类推,在最后剩下2位时,其实只需要看最高位了,因为一开始n赋值位,所以后面用他减去最高为即可,可以自己推理一下。
六、输出一个正整数的大于等于它的最近的2次幂的数
输出一个正整数的大于等于它的最近的2次幂的数,比如输入13,那么输出16,输入16则输出16.
我们这里可以学习HashMap源码中的算法,在其有参构造函数中,如果设定了初始容量,那么在HashMap初始化时会调用一个内部叫做tableSizeFor的方法来计算离该数最近的二次幂来重设容量值,于是我们参照源码这样改写:
1 public static int getNear2Power(int num) { 2 if(num <= 0) { 3 return 0; 4 } 5 int n = num - 1; 6 n |= n >>> 1; 7 n |= n >>> 2; 8 n |= n >>> 4; 9 n |= n >>> 8; 10 n |= n >>> 16; 11 return n + 1; 12 }
这个算法的原理就是,先将这个值减去一,因为要考虑到本身就是2的N次幂的可能,然后再把这个数的二进制表示中,最高位为1的后面全部用1来补齐,补齐之后加一,自然就是最近的大于该数的2次幂的数了,也可以在稿纸上自行推演一番,算法着实巧妙。
转载于:https://www.cnblogs.com/captainad/p/10968103.html
移位和位运算相关算法题学习积累相关推荐
- 数据结构与算法XS班-左程云第一节课笔记(位运算、算法是什么、简单排序)
第1节 位运算.算法是什么.简单排序 ##这是数据结构与算法新手班-左程云第一节课的笔记## 1. 位运算 // 你们会不会表示一个数字的32位啊? // Java中int类型默认以32位二进制数在计 ...
- !codeforces 558C Amr and Chemistry-yy题-(位运算相关)
题意:有n个数,每次进行的操作只能是除以2或者乘以2,求这n个数转换成同一个数字所需要的最小的操作步数 分析: 乍一看题目,觉得好难,对于这种每次有两种情况求最后到达的终点的balabala的我就觉得 ...
- 动态规划+BFS+DFS+回溯+红黑树+排序+链表+位运算(B站优质学习资源链接,后续会继续更新)
动态规划 正月点灯笼(UP主) 个人主页 https://space.bilibili.com/24014925/channel/detail?cid=12580 动态规划第一讲 https://ww ...
- 【231】判断是否是2的次幂--位运算相关
给你一个整数 n,请你判断该整数是否是 2 的幂次方.如果是,返回 true :否则,返回 false . 如果存在一个整数 x 使得 n == 2x ,则认为 n 是 2 的幂次方. 示例 1: 输 ...
- 位运算相关题目-一些小trick 1bit代表独立数字 求只出现一次的数字 无进位n进制数 n(-n) Boyer-Moore 投票算法 n(n-1)
二进制位方法 集合的每个元素,都有可以选或不选,用二进制的位来表示,0表示不选,1表示选自.0x1 << nums.size()-1 的每一位就代表了集合中每个元素都选用.这里由于集合中每 ...
- 【BZOJ4300】绝世好题,位运算相关DP
传送门 思路: 按照每一位来进行DP f[i]f[i]表示最后一个数的第i个二进制为1的最长子序列个数 每次转移时把a[i]a[i]拆成二进制位,然后取数为1的位上f<script type=& ...
- 状压dp解释及位运算相关介绍
状压dp其实和普通dp没有什么区别,主要差别在于要熟练掌握为运算的处理,我自己在这一方面比较菜, 所以特此总结一下,也方便自己以后查阅. 状压dp主要是将当前比较复杂的状压缩到二进制上表示,一般用于处 ...
- 二分搜索相关算法题汇总
二分搜索简介 在计算机科学中,二分搜索(binary search)也称折半搜索(half-interval search).对数搜索(logarithmic search),是在有序数组中查找某一特 ...
- 【代码随想录 | day06】(JavaScript) 哈希表理论基础以及相关算法题
哈希表理论基础 242.有效的字母异位词 349.两个数组的交集 202.快乐数 两数之和 哈希表理论基础 要了解哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set 和map ...
- 数据结构树及相关算法题
树 定义 树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合.把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的.它具有以下的特点: 有一个特 ...
最新文章
- 科普云计算知识,迎接云计算大会
- EfficientNet v2来了 更快、更小、更强
- Windows Nginx 反向代理 Microsoft SQL Server (MSSQL)
- python工作环境_CentOS7下python工作环境管理
- SpringMVC与Ajax交互
- c++ int *p = new int()
- 设计模式 - 七大设计原则(一)
- JAVA并发,线程异常捕获
- 小型空仓库图片_大中型的食品企业为何都青睐自动化立体仓库?
- nginx ---- nginx.conf核心配置文件
- 《算法问题实战策略》-chaper21-树的实现和遍历
- 使用Python进行描述性统计
- spring-第一篇之spring核心机制依赖注入(DI)/控制翻转(IoC)
- Oracle Java认证OCJP考试题库在哪找
- python微积分求面积_用Python学微积分(微积分应用)
- Safari浏览器兼容性问题处理
- Vue 前端根据坐标点按顺序生成连线
- 三、使用HM进行简单的视频隐写demo
- 四种傅里叶变换的简述
- Nature:Deep Learning 深度学习综述
热门文章
- 拓端tecdat|R语言Gabor滤波进行目标图像纹理特征的提取
- python使用自制程序_python--自制程序性能检测工具
- 如何使用Python开发随机森林集成
- Python3 类(2)
- OpenCV实现验证otsu算法
- java的argv_Java:使用org.apache.commons.cli解析传入参数args,该包会协助解析argv参数...
- truffle部署到测试网rinkeby
- 公众号文章发送pdf文件 pdf文件如何变成导出图片
- bootstrap4 图标和文字行内对齐
- Hyperledger fabric v2.3 交易流程 翻译