【LeetCode刷题笔记】(三)位运算

96 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情 这也是第37篇文章

前言

今天总结的主题是——位运算。


先来一道经典的题目

位1的个数

题目

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量

思路

因为我是Java选手,知道在Java中有个Integer.bitCount(int num)的方法可以统计num的二进制形式中的1的个数。

不过在这道题中直接用这个方法肯定是不合适的,因为题目要考察的不是调用api的能力,而是实现api的能力。

用&和<<操作遍历每一位,不为0就计数+1。

代码实现

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

另一道很经典的题目

不用加减乘除做加法

题目

写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号

思路

数字逻辑和计组课告诉我们,其实十进制的“+”、“-”、“*”、“/”都可以用二进制位运算来表示,机器实现上有各种补码加法器等等。

对加法而言,只要抓住两点:

  • 当前位变成什么 异或^的性质是这个位的最佳描述
  • 有没有进位 (对二进制加法而言,如果两个位都为1,就会有进位)

代码实现

class Solution {
    public int add(int a, int b) {
        int cur=b,carry=a;
        while(carry!=0){
            cur=a^b;
            carry=a&b;
            carry=carry<<1;
            a=cur;
            b=carry;
        }
        return cur;
    }
}

这道题位运算的思想有点隐蔽。

只出现一次的数字

题目

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

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

思路

可以用异或^的性质,不同为1,相同为0。

代码实现

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

颠倒二进制位

题目

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

思路

可以新构造一个二进制数,从后往前遍历原二进制的位,将它逐个加到新的二进制数中。

代码实现

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