当前位置: 首页 > article >正文

面试经典150题——位运算

文章目录

  • 1、二进制求和
    • 1.1 题目链接
    • 1.2 题目描述
    • 1.3 解题代码
    • 1.4 解题思路
  • 2、颠倒二进制位
    • 2.1 题目链接
    • 2.2 题目描述
    • 2.3 解题代码
    • 2.4 解题思路
  • 3、位1的个数
    • 3.1 题目链接
    • 3.2 题目描述
    • 3.3 解题代码
    • 3.4 解题思路
  • 4、只出现一次的数字
    • 4.1 题目链接
    • 4.2 题目描述
    • 4.3 解题代码
    • 4.4 解题思路
  • 5、只出现一次的数字 II
    • 5.1 题目链接
    • 5.2 题目描述
    • 5.3 解题代码
    • 5.4 解题思路
  • 6、数字范围按位与
    • 6.1 题目链接
    • 6.2 题目描述
    • 6.3 解题代码
    • 6.4 解题思路


1、二进制求和

1.1 题目链接

点击跳转到题目位置

1.2 题目描述

给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。

提示:

  • 1 <= a.length, b.length <= 104
  • a 和 b 仅由字符 ‘0’ 或 ‘1’ 组成
  • 字符串如果不是 “0” ,就不含前导零

1.3 解题代码

class Solution {
    public String addBinary(String a, String b) {
        int m = a.length();
        int n = b.length();
        int i = m - 1;
        int j = n - 1;
        StringBuffer sb = new StringBuffer();
        int carry = 0;
        while(i >= 0 && j >=0){
            int num1 = a.charAt(i) - '0';
            int num2 = b.charAt(j) - '0';
            int num = (num1 + num2 + carry) % 2;
            carry = (num1 + num2 + carry) / 2;
            sb.append(num);
            --i;
            --j;
        }
        while(i >= 0){
            int num1 = a.charAt(i) - '0';
            int num = (num1 + carry) % 2;
            carry = (num1 + carry) / 2;
            sb.append(num);
            --i;
        }
        while(j >= 0){
            int num2 = b.charAt(j) - '0';
            int num = (num2 + carry) % 2;
            carry = (num2 + carry) / 2;
            sb.append(num);
            --j;
        }
        if(carry == 1){
            sb.append('1');
        }
        sb.reverse();
    return sb.toString();
    }
}

1.4 解题思路

  1. 二进制加法,采用模拟的思路,逐位相加,考虑进位即可。

2、颠倒二进制位

2.1 题目链接

点击跳转到题目位置

2.2 题目描述

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

提示:

  • 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
  • 在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在 示例 2 中,输入表示有符号整数 -3,输出表示有符号整数 -1073741825。

提示:

  • 输入是一个长度为 32 的二进制字符串

2.3 解题代码

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

2.4 解题思路

  1. 使用位运算直接反转,比如第0位的放置到第31位上去。

3、位1的个数

3.1 题目链接

点击跳转到题目位置

3.2 题目描述

给定一个正整数 n,编写一个函数,获取一个正整数的二进制形式并返回其二进制表达式中设置位(set bit 指在某数的二进制表示中值为 1 的二进制位)的个数(也被称为汉明重量)。

提示:

  • 1 <= n <= 231 - 1

3.3 解题代码

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

3.4 解题思路

  1. 公式化题目,每次用n 与 n - 1做位运算,则能去除掉最低位的1.

4、只出现一次的数字

4.1 题目链接

点击跳转到题目位置

4.2 题目描述

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

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

提示:

  • 1 <= nums.length <= 3 * 104
  • -3 * 104 <= nums[i] <= 3 * 104
  • 除了某个元素只出现一次以外,其余每个元素均出现两次。

4.3 解题代码

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

4.4 解题思路

  1. 亦或运算解决问题。

5、只出现一次的数字 II

5.1 题目链接

点击跳转到题目位置

5.2 题目描述

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

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

提示:

  • 1 <= nums.length <= 3 * 104
  • -231 <= nums[i] <= 231 - 1
  • nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次。

5.3 解题代码

class Solution {
    public int singleNumber(int[] nums) {
        int res = 0;
        for(int i = 0; i < 32; ++i){
            int ans = 0;
            for(int j = 0; j < nums.length; ++j){
                ans += (nums[j] >> i) & 1;
            }
            ans %= 3;
            if(ans > 0){
                res ^= (1 << i);
            }
        }
        return res;
    }
}

5.4 解题思路

  1. 使用位运算,计算所有的数在某一位的1的个数,如果是3的倍数,则那个只出现一次的数字在该为为0,否则的话在该位为1。

6、数字范围按位与

6.1 题目链接

点击跳转到题目位置

6.2 题目描述

给你两个整数 left 和 right ,表示区间 [left, right] ,返回此区间内所有数字 按位与 的结果(包含 left 、right 端点)。

提示:

  • 0 <= left <= right <= 231 - 1

6.3 解题代码

class Solution {
    public int rangeBitwiseAnd(int left, int right) {
        int shift = 0;
        while(left < right){
            left >>= 1;
            right >>= 1;
            ++shift;
        }
        return left << shift;
    }
}

6.4 解题思路

  1. 寻找left和right的二进制位的相等前缀即可。

http://www.kler.cn/a/547330.html

相关文章:

  • 零基础学习人工智能
  • 2024问题总结
  • Redis 04章——持久化
  • SPA 收入支出/技师提成自动统计系统——东方仙盟
  • 红黑树:高效平衡二叉树的奥秘
  • Unity嵌入到Winform
  • shell命令脚本(2)——条件语句
  • Ansys Zemax | 使用衍射光学器件模拟增强现实 (AR) 系统的出瞳扩展器 (EPE):第 1 部分
  • 跨平台键鼠共享免费方案--Deskflow!流畅体验用MacBook高效控制Windows设备
  • Java 多线程编程与单例模式
  • 【C语言】程序环境与预处理
  • C++模拟实现二叉搜索树
  • 「软件设计模式」桥接模式(Bridge Pattern)
  • 基于JavaWeb开发的Java+Spring+vue+element实现旅游信息管理平台系统
  • CF 137B.Permutation(Java 实现)
  • CAS单点登录(第7版)20.用户界面
  • 【SLAM】在 ubuntu 18.04 arm 中以ROS环境编译与运行ORB_SLAM3
  • 网络安全防护:开源WAF雷池SafeLine本地部署与配置全流程
  • Java 基于 SpringBoot+Vue 的家政服务管理平台设计与实现
  • S32DS新建工程时不能选择芯片型号