算法通关村第十一关白银挑战——位运算符的高频算法题

news2024/9/28 1:25:09

大家好,我是怒码少年小码。

今天讲讲几个位运算的经典算法。

位移的妙用

1. 位1的个数

LeetCode 191:编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数。

  • 输入:n = 00000000000000000000000000001011
  • 输出:3
  • 解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。
方法一

还记得我们上一篇()最后写的位运算代码套路的获取吗?与运算的特点是只有两边都为1结果才为1,否则结果为零。利用这个特点我们可以解决这个问题,例如数字3和数字1的二进制串进行与运算:

00000000000000000000000000001011
& 00000000000000000000000000000001
= 00000000000000000000000000000001

只用我们把1左移或者把原始数字右移然后进行与运算,结果为1说明这一位上是1,就记录“1”的数量加1,知道把32为都比较完后,有多少个记录就可以了。原始数字右移的代码如下:

int hammingWeight(int n) {
	int count = 0;
	for (int i = 0; i < 32; i++) {
		count += (n >> i) & 1;
	}
	return count;
}
方法二:

按位与运算有个性质:对于整数n,计算n & (n-1)的结果为将n的二进制表示的最后一个1变成0。利用这条性质,令n = n & (n-1),则n最后的二进制表示中的1数量减少一个。例如:

重复该操作,直到n的二进制表示中的全部数位都变成0,则操作次数即为n的位1的个数。代码如下:

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

这两种方法,第一种的循环次数取决于原始数字的位数,第二种取决于原始数字种"1"的个数,效率自然高不少。

###2. 比特位计数

LeetCode 338:给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

  • 输入:n = 2
  • 输出:[0,1,1]
  • 解释:
    0 --> 0
    1 --> 1
    2 --> 10

自己先思考一下这题真的很简单!!

分析:遍历0 <= i <= n中的每一个数字,获取它们二进制串中的“1”的个数(可以单独设置一个函数),然后把个数保存到数组对应的位置上。

    int helper(int n){
        int count = 0;
        while(n != 0){
            n = n & (n-1);
            count++;
        }
        return count;
    }
    vector<int> countBits(int n) {
        vector<int> ans(n+1);
        for(int i =0; i < n+1; i++){
            int count = helper(i);
            ans[i] = count;
        }
        return ans;
    }

这就是一通百通吧😎。

3. 颠倒无符号整数

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

颠倒二进制位

分析:肯定是先要获取某一位,然后再把它放到应该的位置上去。获取就用原始数字与1进行与运算,然后原始数字右移,这样我们就能得到低位置上的二进制数,然后通过左移power个来放到高位

 int reverseBits(int n) {
    int reversed = 0, power = 31;
    while (n != 0) {
        reversed += (n & 1) << power;
        n >>=1;
        power--;
    }
    return reversed;
}

n >>= 1是一个右移操作符,它将变量n的值向右移动一位。类似于n+=1是把n的值加一。

位实现加减乘除专题

在计算机中,位运算的效率比单纯加减乘除的效率更高,因此在高性能软件的源码中大量应用。

1. 位运算实现加法

LeetCode 371:给你两个整数 a 和 b ,不使用 运算符 + 和 - ,计算并返回两整数之和。

两个位加的时候,需要考虑两个问题:进位部分是什么?不进位部分是什么?

  • 对于不进位部分(0+0,1+0,0+1)的情况是:相同为0,不同为1(其实是a⊕b)
  • 对于进位部分(1+1),a和b的这一位都是1的时候才会进位,而且进位只能是1(其实是a&b=1),然后位数由1位变成两位,需要手动移位(a & b) << 1

所以:

  • 不进位部分:用a⊕b计算就可以
  • 是否进位,以及进位值使用(a & b) << 1计算即可
int getSum(int a, int b) {
     while (b != 0) {
         int sign = (a & b) << 1;//计算出哪些位同时为1(这些需要进位)
         a = a ^ b; //无进位和
         b = sign;
     }
     return a;
 }

从低位开始,处理每一位,考虑进位,并逐步向高位移动。

2. 递归乘法

LeetCode 08.05:递归乘法。 写一个递归函数,不使用 * 运算符, 实现两个正整数的相乘。可以使用加号、减号、位移,但要吝啬一些。

示例:

  • 输入: a=1,b=10
  • 输出:10

不用*计算,一种方法是将一个作为循环的参数,对另一个进行累加,但是这样效率太低,所以还要考虑位运算。

首先,需要求得a和b的最小值和最大值,把其中的最小值当做乘数(选最小值当乘数,后续计算算的少),将其拆分成2的幂的和(方便左移),
即min = a0 * 2^0 + a12^1 + a2 2^2 + … + ai2i+…,其中ai取0或者1,相当于用二进制的视角去看待min,比如12用二进制来表示就是1100,即1000+0100
13 * 12 = 13 * (8+4)= 13
8 + 13*4 = (13<<3)+(13<<2);

上面仍然需要左移5次,存在重复计算,可以进一步简化:
假设我们需要的结果是ans
定义临时变量 :tmp = 13<<2 = 52计算后,可以先让ans = 52
然后tmp继续左移一次tmp = 52<<1 = 104,此时再让ans = ans + tmp
此时只要执行三次移位和一次加法

 int multiply(int a, int b) {
     int min = a < b ? a : b;
     int max = a > b ? a : b;
     int ans = 0;
     for (int i = 0; min != 0; i++) {
         if ((min & 1) == 1) {
             ans += max;
         }
         min >>= 1;
         max += max;
     }
     return ans;
 }

END

本文的主要内容来自算法通关村。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1130473.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

html 常见兼容性问题

目录 前言: 用法: 代码: 1. 盒模型差异: 2. 表格布局问题: 3. 浏览器前缀问题: 4. 字体渲染问题: 理解: 讨论: 前言: 在Web开发中&#xff0c;兼容性问题是常见的挑战之一。不同的浏览器和设备可能以不同的方式解释和呈现HTML&#xff0c;导致网页在某些环境下出现问题…

fastjson对象序列化的问题

今天偶然遇到一个fastjson将字符串反序列化为一个对象的时候的问题&#xff0c;就是简单的通过com.alibaba.fastjson.JSON将对象转为字符串&#xff0c;然后再从字符串转换为原类型的对象。 涉及的代码也非常简单 package cn.edu.sgu.www.mhxysy.service.role.impl;import cn…

单片机设计基于STM32的空气净化器设计

**单片机设计介绍&#xff0c;1615[毕设课设]基于STM32的空气净化器设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图pcb设计图 五、 程序六、 文章目录 一 概要 此设计资料主要包含原理图、PCB、源程序、元器件清等资料&#xff0c; 二、功能设计 设计思路 …

uniapp--点击上传图片到oss再保存数据给后端接口

项目采用uniapp与uview2.0组件库 --1.0的也可以参考一下&#xff0c;大差不差 一、项目要求与样式图 点击上传n张图片到oss&#xff0c;然后点击提交给后端 二、思路 1、打开上传按钮&#xff0c;弹出框内出现上传图片和提交按钮 2、点击上传图片区域&#xff0c;打开本地图…

redis持久化之AOF(Append Only File)

1 : AOF 是什么 以日志的形式来记录每个写操作&#xff08;增量保存&#xff09;&#xff0c;将redis执行过的所有写指令记录下来&#xff08;读操作不记 录&#xff09;&#xff0c;只允追加文件但不可改写文件&#xff0c;redis启动之初会读取该文件重新构造数据&#xff0c;…

【Linux】IP协议

文章目录 &#x1f4d6; 前言1. 网络层2. IP协议格式3. IP报文分片和组装3.1 如何分片和组装&#xff1a;3.2 组装的衍生问题&#xff1a; 4. 网段划分&#xff08;重点&#xff09;4.1 子网掩码&#xff1a;4.2 IP地址的数量限制&#xff1a;4.3 私有IP地址和公网IP地址&#…

读高性能MySQL(第4版)笔记19_云端和合规性

1. 如何构建数据库环境 1.1. 托管MySQL 1.2. VM上构建 1.3. 天下没有免费的午餐&#xff0c;每一个选择都伴随着一系列的权衡 2. 托管MySQL 2.1. 服务商提供了一个可访问的数据库设置程序&#xff0c;而不需要用户深入了解MySQL的具体细节 2.2. 使用托管MySQL将缺乏很多的…

vueDay03——计算属性

一、一般场景 当我们需要对某个数据进行简单判断渲染的时候&#xff0c;我们通常会使用如下方法 <div>nginx当前状态&#xff1a;{{ openNginx true ? true : false}} </div> 但是这样就很影响观感&#xff0c;因为渲染出来的只有openNginx的值&#xff0c;而…

微信小程序投票管理系统:打造智能、便捷的投票体验

前言 随着社交网络的兴起和移动互联网的普及&#xff0c;人们对于参与和表达意见的需求越来越强烈。在这个背景下&#xff0c;微信小程序投票管理系统应运而生。它为用户提供了一个智能、便捷的投票平台&#xff0c;使用户可以轻松创建和参与各种类型的投票活动。本文将详细介…

【C++学习笔记】类和对象(上)

目录 1. 面向对象和面向过程的初步认识 2. 类的引入 3. 类的定义 3.1 类的两种定义方式 3.1.1声明和定义全部放在类体中 3.1.2.类声明放在.h文件中&#xff0c;成员函数定义放在.cpp文件中 4. 类的访问限定符及封装 4.1 访问限定符 4.2 面试题&#xff1a;C中struct…

百度文心一言4.0——使用及API测试

登录百度智能云&#xff1a;百度智能云 文心一言4.0使用 开通付费&#xff1a; 创建应用&#xff1a; 自行创建应用名称&#xff1a; 对话测试&#xff1a; API测试 ERNIE-Bot-4 API&#xff1a;ERNIE-Bot-4 打开链接查看自己的API Key&#xff0c;Secret Key。 可参…

Python手搓C4.5决策树+Azure Adult数据集分析

前言 课上的实验 由于不想被抄袭&#xff0c;所以暂时不放完整代码 Adult数据集可以在Azure官网上找到 Azure 开放数据集中的数据集 - Azure Open Datasets | Microsoft Learn 数据集预处理 删除难以处理的权重属性fnlwgt与意义重复属性educationNum去除重复行与空行删除…

从一个页面跳转到目标页面之后,对应的顶部路由高亮

需求&#xff1a;页面跳转到目标页面之后&#xff0c;对应的顶部路由高亮 上面的更多 跳转到 学情分析下面的学生分析 <template><div class"topBar" ref"topBar" v-loading.fullscreen.lock"fullscreenLoading"><div class&quo…

dc9靶机攻略

dc9 扫描 扫描结果如图 nmap 目录扫描 指纹扫描 渗透 访问首页 该处发现搜索框&#xff0c;正常搜名字可以直接返回该用户的信息&#xff0c;怀疑sql注入&#xff0c;使用单引号注入&#xff0c;发现没反应&#xff0c;再使用一下万能注入语句1 or 11 使用sqlmap sqlmap -…

什么是蓝桥杯?什么是蓝桥STEMA考试?

第十五届蓝桥大赛赛事安排? STEMA考试11月(考试时间11月26日) STEMA考试1月(2024年1月) STEMA考试3月(2024年3月) 第十五届蓝桥杯省赛(2024年4月待定) 第十五届蓝桥杯国赛(2024年5月待定) 注:以上时间具体以组委会官方发布为准。 01.蓝桥杯 蓝桥杯全国软件和…

【每日一题】掷骰子等于目标和的方法数

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;动态规划 写在最后 Tag 【动态规划】【数组】 题目来源 1155. 掷骰子等于目标和的方法数 题目解读 你手里有 n 个一样的骰子&#xff0c;每个骰子都有 k 个面&#xff0c;分别标号 1 到 n。给定三个整数 n&#xff0…

部署基于efk+logstash+kafka构建日志收集平台并对nginx日志进行分析

文章目录 1.1 安装zookeeper集群1.2 安装kafka集群1.3 部署filebeat服务1.4 部署logstash1.5 部署es和kibana服务1.6 配置kibana ui界面1.7 对nginx进行日志分析 Filebeat采集日志kafka topic存起来日志->logstash去kafka获取日志&#xff0c;进行格式转换->elasticsearc…

【计算机网络笔记】网络应用进程通信

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

【RocketMQ系列十四】RocketMQ中消息堆积如何处理

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

Elasticsearch分词器-中文分词器ik

文章目录 使用standard analysis对英文进行分词使用standard analysis对中文进行分词安装插件对中文进行友好分词-ik中文分词器下载安装和配置IK分词器使用ik_smart分词器使用ik_max_word分词器 text analysis 使用standard analysis对英文进行分词 ES默认使用standard analys…