Java实现之位运算符

导读:本篇文章讲解 Java实现之位运算符,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

目录

一.& 与运算符

二.| 或运算符

三.^ 异或运算符

四.~ 非运算符

五.<< 左移运算符

六.>>右移运算符

六.>>> 无符号右移: 

七.综合运用

1.将二进制数的第x位置变成1

2.将二进制数的第x位置变成0

3.求二进制中1的个数

4.计算1之间的最大间距

5.只出现一次的数字

6.颠倒二进制位

7.只出现一次的数字 II


一.& 与运算符

当转换为二进制之后,对应位置同时为1的时候才为1

如:Java实现之位运算符

二.| 或运算符

当转换为二进制之后,对应位置有一个为1的时候就为1

Java实现之位运算符

三.^ 异或运算符

当转换为二进制之后,对应位置相同为0,不同为1(或者记住奇数个1为0,偶数个1为1)

Java实现之位运算符

异或的一些小性质:

  1. 任何数和0做异或运算,结果仍然是原来的数,即 a⊕0=a
  2. 任何数和其自身做异或运算,结果是 0,即 a⊕a=0
  3. 异或运算满足交换律和结合律,即 a⊕b⊕a = b⊕a⊕a = b⊕(a⊕a)=b⊕0=b

四.~ 非运算符

反转每一位的二进制,将1变成0,0变成1

Java实现之位运算符

五.<< 左移运算符

将当前数字的二进制形式向右移n位,右边补0,相当于乘以2

Java实现之位运算符

注意:一个数x左移n位,相当于 x*2^n

六.>>右移运算符

将当前数字的二进制形式向右移n位,左边补(正数补0,负数补1),相当于除以2

Java实现之位运算符

六.>>> 无符号右移: 

即右移之后,无论该数为正还是为负,右移之后左补0。

七.综合运用

1.将二进制数的第x位置变成1

    /**
     *
     * @param num   需要置1的数字
     * @param position  需要置1的位置
     * @return   置1后的数字
     */
    public static int changetoOne(int num,int position){
        num|=(1<<(position-1));
        return num;

    }

测试数据:

changetoOne(8, 2);  //10

Java实现之位运算符

2.将二进制数的第x位置变成0

    /**
     *
     * @param num   需要置0的数字
     * @param position  需要置0的位置
     * @return   置0后的数字
     */
    public static int changetoZero(int num,int position){
        num&=~(1<<(position-1));
        return num;
    }

测试数据:

changetoZero(15, 2);  //13

Java实现之位运算符

3.求二进制中1的个数

当求二进制中1的个数

可以使用res&=(res-1),这样可以去掉二进制中的最后一个1;

    /**
     *
     * @param num  所要求的数
     * @return  二进制总共含有多少个1
     */
    public static int countOne(int num){
        int count=0;
        while (num!=0){
            num&=num-1;
            count++;
        }
        return count;
    }
countOne(217);   //5

Java实现之位运算符,以此类推,总共5个1

4.计算1之间的最大间距

力扣:力扣

给定一个正整数 n,找到并返回 n 的二进制表示中两个 相邻 1 之间的 最长距离 。如果不存在两个相邻的 1,返回 0

如果只有 0 将两个 1 分隔开(可能不存在 0 ),则认为这两个 1 彼此 相邻 。两个 1 之间的距离是它们的二进制表示中位置的绝对差。例如,"1001" 中的两个 1 的距离为 3 。

 /**
     * @param n 所要求解的数字
     * @return 二进制之间1的最大间距
     */
    public static int binaryGap(int n) {
        int start = 0, end = 0, max = 0;//start为开始1的位置,end为结束1的位置,max记录end-start的最大值

        while ((n & 1) != 1) {//判断n的最后一位是否为1
            start++;
            n = n >> 1;//每一次后移一位

        }
        if (n == 1)//当n等于1的时候,说明n中仅含有1个1
            return 0;
        end = start;//将start变为end

        while (n != 0) {
            end++;
            if ((n & 1) == 1) {//判断n的最后一位是否为1
                max = Math.max(max, end - start);
                start = end;
            }
            n = n >> 1;//每一次后移一位

        }
        return max;
    }

5.只出现一次的数字

力扣:力扣

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

分析:阅读题目可以知道,只有一个元素出现一次,其他的数字出现且仅出现了两次,这个时候就可以使用异或运算来进行操作

  1. 任何数和0做异或运算,结果仍然是原来的数,即 a⊕0=a
  2. 任何数和其自身做异或运算,结果是 0,即 a⊕a=0
  3. 异或运算满足交换律和结合律,即 a⊕b⊕a = b⊕a⊕a = b⊕(a⊕a)=b⊕0=b

由此就可以写出代码了

    public int singleNumber(int[] nums) {
        int single = 0;
        for (int i = 0; i < nums.length; ++i) {
            single ^= nums[i];
        }
        return single;
    }

6.颠倒二进制位

力扣:力扣

颠倒给定的 32 位无符号整数的二进制位。

    public int reverseBits(int n) {
        int rev = 0;
        for (int i = 0; i < 32 && n != 0; ++i) {
            //每次将数n第x位上的送到第33-x位上
            rev |= (n & 1) << (31 - i);
            //每次的无符号右移只是为了n & 1可以求出第x位上的数字是1还是0
            n >>>= 1;
        }
        return rev;
        
    }

7.只出现一次的数字 II

力扣:力扣

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法且不使用额外空间来解决此问题。

    public int singleNumber(int[] nums) {
        int res=0;
        for(int i=0;i<32;++i){
            int total=0;
            for (int num : nums) {
                total+=(num>>i)&1;
            }
            if (total % 3 != 0)
                res |= 1 << i;
        }
        return res;

    }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/101062.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!