位运算技巧&题目应用

常见技巧

https://blog.csdn.net/Apple_hzc/article/details/83830118
https://blog.csdn.net/weixin_39003229/article/details/90488161
https://www.wandouip.com/t5i204483/

//https://blog.csdn.net/zmazon/article/details/8262185

public class 位运算 {
    public static void main(String[] args) {
        System.out.println(getMaxInt());
        System.out.println(getMinInt());
        System.out.println(getMaxLong());
        System.out.println(multi2Power(3,3));//3*2^3=24
        System.out.println(isOddNumber(9));
        swap(4,3);
        System.out.println(absNum(-11101));
        System.out.println(maxNum(9,-1));
        System.out.println(isSameSign(8,1));
        System.out.println(isFactorialofTwo(45));
    }
    //不用临时变量  交换两个数
    public static void swap(int a,int b){
        System.out.println("交换前a: "+a+",b: "+b);
        a^=b;//a=a^b;
        b^=a;//b=(a^b)^b=a
        a^=b;//a=(a^b)^a=b
        System.out.println("交换后a: "+a+",b: "+b);
    }

    //判断两个数符号是否一致
    //对于任何数x,都有x^x=0,x^0=x
    //判断符号位 0和1异或时符号位为1 其他均为0
    public static boolean isSameSign(int x, int y){ //有0的情况例外 8和0判定为一样了
        System.out.println(x ^ y);
        return (x ^ y) >= 0; // true 表示 x和y有相同的符号, false表示x,y有相反的符号。
    }
    //计算2的n次方
    public static int getFactorialofTwo(int n){//n > 0
        return 2 << (n-1);//2的n次方
    }
    //判断一个数是否是2的次方
    /*如果是2的幂,n一定是100... n-1就是011....
	   所以做与运算结果为0*/
    public static boolean isFactorialofTwo(int n){
        return n>0?(n&(n-1))==0:false;
    }

    //对2的n次方取余
    public static int mod2(int m,int n){//n为2的次方
        return m & (n - 1);
	/*如果是2的幂,n一定是100... n-1就是1111....
	 所以做与运算结果保留m在n范围的非0的位*/
    }

    //取平均值
    public static int getAverage(int x, int y) {
        return (x + y) >> 1;
    }

    //从低位到高位,取n的第m位
    public static int getBit(int n, int m){
        return (n>>(m-1))&1;
    }

    //从低位到高位.将n的第m位置1
    public static int setBitToOne(int n, int m){
        return n | (1 << (m-1));
	/*将1左移m-1位找到第m位,得到000...1...000
	  n在和这个数做或运算*/
    }

    //从低位到高位,将n的第m位置0
    public static int setBitToZero(int n, int m){
        return n & ~(1 << (m-1));
	/* 将1左移m-1位找到第m位,取反后变成111...0...1111
	   n再和这个数做与运算*/
    }




    //判断一个数奇数true  偶数false
    public static boolean isOddNumber(int n){
        return (n&1)==1;//偶数末位0  奇数末位1
    }

    //获得int类型最大值
    public static int getMaxInt(){
        //return (1<<31)-1;//写法1
        //return ~(1<<31);//写法2
        return (1<<-1)-1;//写法3
    }
    //获得int类型最小值
    public static int getMinInt(){
        //return 1<<31;//写法1
        return 1<<-1;//写法3
    }
    //获得long类型最大值
    public static long getMaxLong(){
//        return ((long)1<<127)-1;//写法1
//        return ~((long)1<<127);//写法2
        return ((long)1<<-1)-1;//写法3
    }
    //n乘以2的m次方
    public static int multi2Power(int n,int m){
        return n<<m;//除以 n>>m
    }


    //取绝对值
    /* n>>31 取得n的符号,若n为正数,n>>31等于0,若n为负数,n>>31等于-1
若n为正数 n^0=0,数不变,若n为负数有n^-1 需要计算n和-1的补码,然后进行异或运算,
结果n变号并且为n的绝对值减1,再减去-1就是绝对值 */
    public static int absNum(int n){
        return (n ^ (n >> 31)) - (n >> 31);
    }

    //取两数较大值
    public static int maxNum(int a,int b){
        return b & ((a-b) >> 31) | a & (~(a-b) >> 31);
        /*如果a>=b,(a-b)>>31为0,否则为-1*/
    }

    //取两数较小值
    public static int min(int a,int b){
        return a & ((a-b) >> 31) | b & (~(a-b) >> 31);
        /*如果a>=b,(a-b)>>31为0,否则为-1*/
    }
}

136. 只出现一次的数字

class Solution {
    public int singleNumber(int[] nums) {
        //一个数与所有其他数异或 结果都不为0
        //结果就是这个数字
        //此题确定了其他数字都是两次 彼此注定抵消
        //全部异或  结果就是单个的那个数
        int res=0;
        for(int i=0;i<nums.length;i++){
            res^=nums[i];
        }
        return res;
    }
}
//另一种HashMap法
class Solution {
    public int singleNumber(int[] nums) {
        if(nums==null||nums.length==0){
            return 0;
        }
        Map<Integer,Integer> map=new HashMap<>();
        for(int n:nums){
            map.put(n,map.getOrDefault(n,0)+1);
        }
        for(int key:map.keySet()){
            if(map.get(key)==1){
                return key;
            }
        }
        return 0;
    }
}

268. 丢失的数字

class Solution {
    public int missingNumber(int[] nums) {
        if(nums==null||nums.length==0){
            return -1;
        }
        int len=nums.length;
        int sum=0;
        for(int n:nums){
            sum+=n;
        }
        // int expected=0;
        // for(int i=1;i<len+1;i++){
        //     expected+=i;
        // }
        int expected=len*(len+1)/2;
        return expected-sum;
    }
}
class Solution {
    public int missingNumber(int[] nums) {
        if(nums==null||nums.length==0){
            return -1;
        }
        int missing=nums.length;
        for(int i=0;i<nums.length;i++){
            missing^=i^nums[i];
        }
        return missing;
    }
}

191. 位1的个数

踩坑注意

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int count=0;
        while(n!=0){
            //count+=((n&1)==1)?1:0;
            count+=n&1;
            n>>>=1;//逻辑右移  高位填补0
            //n>>=1;//会超时 算术右移  一直补充符号位1
        }
        return count;
    }
}

改进

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int count=0;
        while(n!=0){
            count++;
            n&=n-1;
        }
        return count;
    }
}

231. 2 的幂

class Solution {
    public boolean isPowerOfTwo(int n) {
        return n>0?(n&(n-1))==0:false;
    }
}

https://leetcode-cn.com/problems/power-of-two/solution/2de-mi-by-leetcode-solution-rny3/

n&(n-1)

n&(-n)

class Solution {
    public boolean isPowerOfTwo(int n) {
        return n > 0 && (n & -n) == n;
    }
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/power-of-two/solution/2de-mi-by-leetcode-solution-rny3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

326. 3的幂

class Solution {
    public boolean isPowerOfThree(int n) {
        if(n<=0) return false;
        if(n==1) return true;
        if(n%3!=0) return false;
        else return isPowerOfThree(n/3);
    }
}
class Solution {
    public boolean isPowerOfThree(int n) {
        //换底公式 log3(n)为整数   log10(n)/log10(3)
        return (Math.log10(n)/Math.log10(3))%1==0;
    }
}

342. 4的幂

class Solution {
    public boolean isPowerOfFour(int n) {
        return n>0 && (n&(n-1))==0 && n % 3==1;
    }
}

461. 汉明距离

类似于191

class Solution {
    public int hammingDistance(int x, int y) {
        //异或 0^0=0 0^1=1 1^1=0
        return Integer.bitCount(x^y);//内置函数 计算1的位数
    }
}
class Solution {
    public int hammingDistance(int x, int y) {
        int res=x^y;
        int count=0;
        while(res!=0){
            res&=res-1;
            count++;
        }
        return count;
    }
}

201. 数字范围按位与

右边只要有一个0 与的结果就是0
只要计算最长公共前缀就行
题解

class Solution {
    public int rangeBitwiseAnd(int left, int right) {
        while(left<right){
            right&=right-1;
        }
        return right;
    }
}

371. 两整数之和

https://leetcode-cn.com/problems/sum-of-two-integers/solution/li-yong-wei-cao-zuo-shi-xian-liang-shu-qiu-he-by-p/

class Solution {
    public int getSum(int a, int b) {
        while(b!=0){
            //先计算无进位 的 和
            int tmpSum=a^b;
            // 计算 进位   &和左移1位  更新b用于下一次和a相加
            b=(a&b)<<1;
            //更新a
            a=tmpSum;
        }
        return a;
    }
}
public int getSum(int a, int b) {
    return b == 0 ? a : getSum((a ^ b), (a & b) << 1);
}

190. 颠倒二进制位

public class Solution {
    // you need treat n as an unsigned value
    public int reverseBits(int n) {
        int cnt=32;
        int res=0;
        while(cnt-->0){
            res<<=1;
            res+=n&1;
            n>>=1;
            // cnt--;
        }
        return res;
    }
}

898. 子数组按位或操作

题解

在这里插入代码片

260. 只出现一次的数字 III

405. 数字转换为十六进制数

169. 多数元素

477. 汉明距离总和

421. 数组中两个数的最大异或值

187. 重复的DNA序列

289. 生命游戏

476. 数字的补数

693. 交替位二进制数

318. 最大单词长度乘积

338. 比特位计数

389. 找不同

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值