最近逛博客发现几个很有意思的算法题,大都是二进制相关的移位和位运算相关的,为此我暂且归为一类来整理学习,这也为后续遇到同等问题可以提供解法和思路。

当前文章基于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

移位和位运算相关算法题学习积累相关推荐

  1. 数据结构与算法XS班-左程云第一节课笔记(位运算、算法是什么、简单排序)

    第1节 位运算.算法是什么.简单排序 ##这是数据结构与算法新手班-左程云第一节课的笔记## 1. 位运算 // 你们会不会表示一个数字的32位啊? // Java中int类型默认以32位二进制数在计 ...

  2. !codeforces 558C Amr and Chemistry-yy题-(位运算相关)

    题意:有n个数,每次进行的操作只能是除以2或者乘以2,求这n个数转换成同一个数字所需要的最小的操作步数 分析: 乍一看题目,觉得好难,对于这种每次有两种情况求最后到达的终点的balabala的我就觉得 ...

  3. 动态规划+BFS+DFS+回溯+红黑树+排序+链表+位运算(B站优质学习资源链接,后续会继续更新)

    动态规划 正月点灯笼(UP主) 个人主页 https://space.bilibili.com/24014925/channel/detail?cid=12580 动态规划第一讲 https://ww ...

  4. 【231】判断是否是2的次幂--位运算相关

    给你一个整数 n,请你判断该整数是否是 2 的幂次方.如果是,返回 true :否则,返回 false . 如果存在一个整数 x 使得 n == 2x ,则认为 n 是 2 的幂次方. 示例 1: 输 ...

  5. 位运算相关题目-一些小trick 1bit代表独立数字 求只出现一次的数字 无进位n进制数 n(-n) Boyer-Moore 投票算法 n(n-1)

    二进制位方法 集合的每个元素,都有可以选或不选,用二进制的位来表示,0表示不选,1表示选自.0x1 << nums.size()-1 的每一位就代表了集合中每个元素都选用.这里由于集合中每 ...

  6. 【BZOJ4300】绝世好题,位运算相关DP

    传送门 思路: 按照每一位来进行DP f[i]f[i]表示最后一个数的第i个二进制为1的最长子序列个数 每次转移时把a[i]a[i]拆成二进制位,然后取数为1的位上f<script type=& ...

  7. 状压dp解释及位运算相关介绍

    状压dp其实和普通dp没有什么区别,主要差别在于要熟练掌握为运算的处理,我自己在这一方面比较菜, 所以特此总结一下,也方便自己以后查阅. 状压dp主要是将当前比较复杂的状压缩到二进制上表示,一般用于处 ...

  8. 二分搜索相关算法题汇总

    二分搜索简介 在计算机科学中,二分搜索(binary search)也称折半搜索(half-interval search).对数搜索(logarithmic search),是在有序数组中查找某一特 ...

  9. 【代码随想录 | day06】(JavaScript) 哈希表理论基础以及相关算法题

    哈希表理论基础 242.有效的字母异位词 349.两个数组的交集 202.快乐数 两数之和 哈希表理论基础 要了解哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set 和map ...

  10. 数据结构树及相关算法题

    树 定义 树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合.把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的.它具有以下的特点: 有一个特 ...

最新文章

  1. 科普云计算知识,迎接云计算大会
  2. EfficientNet v2来了 更快、更小、更强
  3. Windows Nginx 反向代理 Microsoft SQL Server (MSSQL)
  4. python工作环境_CentOS7下python工作环境管理
  5. SpringMVC与Ajax交互
  6. c++ int *p = new int()
  7. 设计模式 - 七大设计原则(一)
  8. JAVA并发,线程异常捕获
  9. 小型空仓库图片_大中型的食品企业为何都青睐自动化立体仓库?
  10. nginx ---- nginx.conf核心配置文件
  11. 《算法问题实战策略》-chaper21-树的实现和遍历
  12. 使用Python进行描述性统计
  13. spring-第一篇之spring核心机制依赖注入(DI)/控制翻转(IoC)
  14. Oracle Java认证OCJP考试题库在哪找
  15. python微积分求面积_用Python学微积分(微积分应用)
  16. Safari浏览器兼容性问题处理
  17. Vue 前端根据坐标点按顺序生成连线
  18. 三、使用HM进行简单的视频隐写demo
  19. 四种傅里叶变换的简述
  20. Nature:Deep Learning 深度学习综述

热门文章

  1. 拓端tecdat|R语言Gabor滤波进行目标图像纹理特征的提取
  2. python使用自制程序_python--自制程序性能检测工具
  3. 如何使用Python开发随机森林集成
  4. Python3 类(2)
  5. OpenCV实现验证otsu算法
  6. java的argv_Java:使用org.apache.commons.cli解析传入参数args,该包会协助解析argv参数...
  7. truffle部署到测试网rinkeby
  8. 公众号文章发送pdf文件 pdf文件如何变成导出图片
  9. bootstrap4 图标和文字行内对齐
  10. Hyperledger fabric v2.3 交易流程 翻译