算法必刷系列之位运算

位运算

位运算既能在某些条件下提升运算速度,又能在某些条件下节省运算内存。计算机底层涉及大量位运算,位运算可以替代加加减乘除。位运算的基本运算单元是bit,相比于整数的int占据四个字节,大量节约运算空间,适用于海量数据处理

位1的个数

leetcode191
通过1移位并与给出的数字进行与运算判断对应位置是否位1

public int hammingWeight(int n) {
    int count = 0;
    for(int i=0;i<32;i++){
        int res = n&(1<<i);
        if(res!=0){
            count++;
        }
    }
    return count;
}

比特位计数

leetcode338
将某个数字与该数字减1的数字进行与运算,可以使该数字的最后一个为1的bit位变为0,重复操作,直至该数字为0,操作次数就是bit位1的个数

public int[] countBits(int n) {
    int[] counts = new int[n+1];
    for(int i=0;i<n+1;i++){
        counts[i] = count(i);
    }
    return counts;
}

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

颠倒32位无符号整数

leetcode190
不断从无符号整数的末尾取比特位,左移31-对应位置,遍历结束之后,完成反转

public int reverseBits(int n) {
    int reverseN = 0;
    for(int i=0;i<32;i++){
        int res = n&(1<<i);
        if(res!=0){
            reverseN += (1<<(31-i));
        }
	}
}  

两整数之和

leetcode371
通过与运算计算进位,通过亦或运算进行不包括进位的加法,然后再将进位相加,重复这个过程,直至进位为0

public int getSum(int a, int b) {
     while(b!=0){
         int sign = (a&b)<<1;
         a=a^b;
         b=sign;
     }
     return a;
}

递归乘法

leetcode08.05
通过将乘数中较小的数字拆分成2的n次方的形式,并通过移位运算实现乘法,之所以选择较小的乘数是因为运算次数少

public int multiply(int A, int B) {
    int res = 0;
    int min = Math.min(A,B);
    int max = Math.max(A,B);
    for(int i=0;i<32;i++){
        int temp = min&(1<<i);
        if(temp!=0){
            res+=(max<<i);
        }
    }
    return res;
}

4KB内存寻找重复元素

给定一个数组,数组中包含N个数字,N最大为32000,数组中存在重复数字,且N的大小不确定,要求用4KB内存实现输出数组中的所有重复数字

32000个数字使用int类型存储,内存是肯定大于4KB的。我们可以考虑使用bit数组来实现,数组的下标代表数字,bit位为0代表没有出现,bit位为1代表已经出现,进行输出

public class Bit {
    public void checkDuplicates(int[] array){
        BitSet bs = new BitSet(32000);
        for (int i = 0; i < array.length; i++) {
            int num = array[i];
            int num0 = num-1;
            if(bs.get(num0)){
                System.out.println(num);
            }else {
                bs.set(num0);
            }
        }
    }
}

class BitSet {
    int[] bitSet;

    public BitSet(int size) {
        this.bitSet = new int[size >> 5];
    }

    boolean get(int pos) {
        int wordNumber = pos >> 5;
        int bitNumber = pos & 0x1F;
        return (bitSet[wordNumber]&(1<<bitNumber))!=0;
    }
    
    void set(int pos){
        int wordNumber = pos >> 5;
        int bitNumber = pos & 0x1F;
        bitSet[wordNumber] |= (1<<bitNumber);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天不coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值