位运算的妙用

内容来自微信公众号 [算法与数据结构],整理起来,方便查看

判断一个正整数是不是2的乘方

原理图

微信图片_20171016151523.jpg

代码实现

     /**
     * 判断一个正整数是否是2的乘方
     * @param number 正整数
     * @return 1,2,4,8,16 true 6false
     */
    public static boolean isPowerOf2(int number){
        return (number&(number-1))==0;
    }

求出一个正整数转换成二进制后的数字“1”的个数

原理

一个数N,N&1 要么是0,要么是1。
所以,结果为1时,说明最低位是1。为0时,说明最低位不是1。
因此,每次&后,都右移一位,再次&,直到N右移为0时,结束循环

代码实现

    /**
     * 求出一个正整数转换成二进制后的数字“1”的个数
     * @param number 需要计算的正整数
     * @return 个数
     */
    public static int countNumberBit1(int number){
        int count=0;
        while (true){
            if((number&1)==1){
                count++;
            }
            number>>=1;
            if(number==0){
                break;
            }
        }
        return count;
    }

jdk中Integer封装类中的方法

     /**
     * Returns the number of one-bits in the two's complement binary
     * representation of the specified {@code int} value.  This function is
     * sometimes referred to as the <i>population count</i>.
     *
     * @param i the value whose bits are to be counted
     * @return the number of one-bits in the two's complement binary
     *     representation of the specified {@code int} value.
     * @since 1.5
     */
    public static int bitCount(int i) {
        // HD, Figure 5-2
        i = i - ((i >>> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        return i & 0x3f;
    }

一个无序数组里有99个不重复正整数,范围从1到100,唯独缺少一个整数。如何找出这个缺失的整数?

解法:很简单也很高效的方法,先算出1+2+3….+100的和,然后依次减去数组里的元素,最后得到的差,就是唯一缺失的整数。假设数组长度是N,那么该解法的时间复杂度是O(N),空间复杂度是O(1)。

题目扩展:一个无序数组里有若干个正整数,范围从1到100,其中99个整数都出现了偶数次,只有一个整数出现了奇数次(比如1,1,2,2,3,3,4,5,5),如何找到这个出现奇数次的整数?

解法

遍历整个数组,依次做异或运算。由于异或在位运算时相同为0,不同为1,因此所有出现偶数次的整数都会相互抵消变成0,只有唯一出现奇数次的整数会被留下

代码实现

public static int findSingle(int[] array){
    int result=0;
    for(int i=0,length=array.length;i<length;i++){
        result^=array[i];
     }
    return result;
  }

题目第二次扩展:一个无序数组里有若干个正整数,范围从1到100,其中98个整数都出现了偶数次,只有两个整数出现了奇数次(比如1,1,2,2,3,4,5,5),如何找到这个出现奇数次的整数?

解法

遍历整个数组,依次做异或运算。由于数组存在两个出现奇数次的整数,所以最终异或的结果,等同于这两个整数的异或结果。这个结果中,至少会有一个二进制位是1(如果都是0,说明两个数相等,和题目不符)。

举个例子,如果最终异或的结果是5,转换成二进制是00000101。此时我们可以选择任意一个是1的二进制位来分析,比如末位。把两个奇数次出现的整数命名为A和B,如果末位是1,说明A和B转为二进制的末位不同,必定其中一个整数的末位是1,另一个整数的末位是0。

根据这个结论,我们可以把原数组按照二进制的末位不同,分成两部分,一部分的末位是1,一部分的末位是0。由于A和B的末位不同,所以A在其中一部分,B在其中一部分,绝不会出现A和B在同一部分,另一部分没有的情况。

这样一来就简单了,我们的问题又回归到了上一题的情况,按照原先的异或解法,从每一部分中找出唯一的奇数次整数即可。

假设数组长度是N,那么该解法的时间复杂度是O(N)。把数组分成两部分,并不需要借助额外存储空间,完全可以在按二进制位分组的同时来做异或运算,所以空间复杂度仍然是O(1)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本来定好每个星期写一遍算法的博客的,可是因为最近赶项目,博客停止更新一段时间了,现在抽空继续更新。本来心情挺好的,...
    GitHubClub阅读 5,922评论 0 5
  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-code.h...
    eddy_wiki阅读 13,070评论 0 30
  • 熵 一种信息化的描述方法,用来定义信息中不确定因素的多少。机器学习结果的好坏评判标准就是两类信息之间的熵最小,由此...
    readilen阅读 4,763评论 0 1
  • 遇见 是匆忙的客套 是寂寞的寒暄 还是我 不折不挠的设计 雨天 打湿一地想念 屋檐下偷偷看你的侧脸 是短暂时光里的...
    程姑娘12138阅读 1,852评论 3 4
  • 我看到晨曦 柔柔的洒在海面 夜色中 鳞鳞波光 正簇拥着翻腾的黄浦江 有一个足迹 在那里徜徉 陆家嘴 正审视着国人的...
    江城妖怪阅读 1,313评论 0 0