位运算的一些算法问题

写这篇文章是因为最近在刷LeetCode的算法题但是每次,都没有得心应手的解决方法和思路,每次都要看解答.觉得需要把刷过的题做个总结.位运算在计算机的运行计算速度是相当的快的

基础知识:

  1. &与运算:两个都为true(1),结果才是true(1)
  2. |或运算:两个中一个为false(0),结果就是false(0)
  3. ~取反运算:true取反 成false, false 取反为true.
  4. ^异或运算:相同的为0(想象成两个男的或者两个女的在一起)显然是不允许的,所以为false.

异或运算:
A = 001010
B = 101100
A ^ B = 100110

  1. 左移和右移:
    1. 左移:A<<B,将A的二进制表示的每一位向左移B位,左边超出的位截掉,右边不足的位补0
    2. 右移:也是能很快实现除法运算N >> n即表示右移n位,相当于除以2的n幂
      1. 有符号右移(算数右移):空缺的数补齐符号位的数
      2. 无符号右移(逻辑右移):不管符号位是什么前面补0

下面是一些LeetCode遇到的一些问题:

LeetCode136. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
由基础知识4可知,一个数异或一个数偶数次,还是他本身,题中只有一个元素出现一次,而其他的都出现的了两次.刚好可以利用异或运算的性质来解决.

class Solution {
    public int singleNumber(int[] nums) {
        int ans = 0;
        for(int num: nums) {
            ans ^= num;
        }
        return ans;
    }
}

LeetCode191. 位1的个数

n和n-1的关系
有图可知,n-1会将n的从右向左第一个不是0的数变成0,且后面的数变成1,由基础知识1可知,与运算(n&n-1)会将变化的数都归为0.我们只需要设置一个变量表示一共有多少的1经过了此上述过程即可.

public class Solution {
    public int hammingWeight(int n) {
        int count =0;
        while(n!=0){
            count++;
            n = n&(n-1);
        }
        return count;
    }
}

LeetCode231. 2的幂

给定一个整数,编写一个函数来判断它是否是 2 的幂次方。
方法一:
我们可以发现2的幂在二进制中只有一个1,所以可以把问题转化为求二进制数中1的个数.

class Solution {
	//2的幂次方中,二进制只有一位是1
    public boolean isPowerOfTwo(int n) {
    	//考虑特殊情况
        if(n<0 ){return false;}
        int count =0;
        while(n!= 0){
            count++;
            n &= n-1;
        }
        return count ==1;
    }
}

方法二:
和上面方法差不多,n如果为2的幂,那么n-1这个数只有一位是0其他都是1,可以用与运算,看是否为0;

  • n 二进制最高位为 1,其余所有位为 0;
  • n−1 二进制最高位为 0,其余所有位为 1;
  • 一定满足 n > 0。
class Solution {
    public boolean isPowerOfTwo(int n) {
        return n > 0 && (n & (n - 1)) == 0;
    }
}

LeetCode371. 两整数之和

不使用运算符 + 和 - ​​​​​​​,计算两整数 ​​​​​​​a 、b ​​​​​​​之和。

  • 在位运算操作中,异或的一个重要特性是无进位加法(基础4)。
  • 所以利用与运算和异或即可解答
  1. a + b 的问题拆分为 (a 和 b 的无进位结果) + (a 和 b 的进位结果)
  2. 无进位加法使用异或运算计算得出
  3. 进位结果使用与运算和移位运算计算得出
  4. 循环此过程,直到进位为 0
class Solution {
    public int getSum(int a, int b) {
        int sum =a;
        while(b !=0){
            sum =a^b;
            b =(a & b)<< 1;
            a =sum;
        }
        return sum;
    }
}

结语:

就先写这么多以后刷到别的再添加,如果大家觉得有帮助的,点赞支持下啦~,或者有建议的可以评论。非科班自学学习不易。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值