算法5--位运算

news/2025/1/11 4:15:44/

目录

  • 基础
  • 经典例题
    • [面试题 01.01. 判定字符是否唯一](https://leetcode.cn/problems/is-unique-lcci/description/)
    • [268. 丢失的数字](https://leetcode.cn/problems/missing-number/description/)
    • [371. 两整数之和](https://leetcode.cn/problems/sum-of-two-integers/description/)
    • [137. 只出现一次的数字 II](https://leetcode.cn/problems/single-number-ii/description/)
    • [面试题 17.19. 消失的两个数字](https://leetcode.cn/problems/missing-two-lcci/description/)

基础

基本的位运算符有:

<<  >>  ^  ~  &  |

对于这些位运算之间的优先级没有必要记忆,统一加括号即可。
异或操作就是进行无进位相加,有以下规律:

a^0=a
a^a=0
a^b=b^a
a^b^a=b

下面总结一下使用这些位运算符常见的操作:

  1. 求一个整数n的二进制位的第x(0开始)个比特位是0还是1
(n>>x)&1
  1. 将一个整数的二进制位的第x位改为0
n=n&(~(1<<x))
  1. 将一个整数的二进制位的第x位改为1
n=n|(1<<x)
  1. 提取出整数n最右侧的1
n=n&(-n)

在这里插入图片描述
取负数后,最右侧的1所在位置左侧的比特位都取反了,右侧的及当前位置的比特位数保持不变,且右侧位置的比特位全是0

  1. 去除整数n最右侧的1
n=n&(n-1)

在这里插入图片描述
n-1会向n中最右侧的1借1,从而将其置0,该位置左侧的比特位保持不变,右侧比特位全置1,且在n中该位置右侧比特位是全0

  1. 位图

使用一个比特位(也可以多个)标识数据的状态,要根据具体问题实现

经典例题

面试题 01.01. 判定字符是否唯一

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。
0 <= len(s) <= 100
s[i]仅包含小写字母
如果你不使用额外的数据结构,会很加分。

解法一:使用一个哈希表
解法二:使用一张位图,由于只有26个字符,因此使用一个32位整型类型作为位图即可

class Solution {
public:bool isUnique(string astr) {if(astr.size() > 26){return false;} int bitMap = 0;int i = 0;for (; i < astr.size(); ++i) {int tmp = 1 << (astr[i] - 'a');if (bitMap & tmp) {return false;}bitMap |= tmp;}return true;}
};

268. 丢失的数字

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

解法一:利用等差数列求和公式对[0,n]求和得到sum,sum在减去nums的和即可

class Solution {
public:int missingNumber(vector<int>& nums) {long long int sum1=(nums.size()*(1+nums.size()))/2.0;long long int sum2=0;for(auto e:nums){sum2+=e;}return sum1-sum2;}
};

解法二:利用规律a^a=0,a^0=a,先对[0,n]一一异或得到tmp,再用tmp和nums一一异或即可得到缺失的数字

int missingNumber(int* nums, int numsSize)
{int missnum=0;int i=numsSize+1;while(i--){missnum^=i;}i=numsSize;while(i--){missnum^=nums[i];}return missnum;
}

371. 两整数之和

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

解法1:利用位运算符模拟二进制加法过程

class Solution {
public:int getSum(int a, int b) {int ans=0;int tmp=0;//进位int i=0;for(;i<32;++i){int t1=1&(a>>i);int t2=1&(b>>i);if((t1||t2||tmp)&&(!((t1&&t2&&!tmp)||(tmp&&t2&&!t1)||(tmp&&t1&&!t2)))){ans|=1<<i;tmp=0;}if((t1&&t2)||(t1&&tmp)||(t2&&tmp)){tmp=1;}}return ans;}
};

解法二:a^b就得到a和b的无进位相加m,(a&b)<<1就得到a和b的进位n,可以令a=m,b=n,重复以上过程,直到进位n为0为止

class Solution {
public:int getSum(int a, int b) {while(b){int m=a^b;int n=(a&b)<<1;a=m;b=n;}return a;}
};

137. 只出现一次的数字 II

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的
算法且使用常数级空间来解决此问题。

记录所有的整数对应的比特位为1的频率,将这些频率进行模3运算,得到的就是只出现一次的整数对应的比特位

class Solution {
public:int singleNumber(vector<int>& nums) {vector<int> bit(32,0);int i=0;for(;i<nums.size();++i){int j=0;for(;j<32;++j){bit[31-j]+=1&(nums[i]>>j);bit[31-j]%=3;}}int ans=0;for(i=0;i<32;++i){ans|=bit[i]<<(31-i);}return ans;}
};

面试题 17.19. 消失的两个数字

给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?
以任意顺序返回这两个数字均可。

假设缺的数字是a和b,先对[1,N]异或得到tmp,再用tmp对数组nums一一异或得到的结果就是a^b,由于a和b是不同的两个数字,那么a^b一定有一个比特位为1,假设a^b的第x个比特位为1,现在[0,N]分为第x个比特位为0和为1的两组数字tmp1和tmp2,再将数组nums也分为第x个比特位为0和为1的两组数字nums1和nums2,此时将tmp1和nums1的数字一一异或即可得到a,将tmp2和nums2的数字一一异或即可得到b

class Solution {
public:vector<int> missingTwo(vector<int>& nums) {int tmp = 0; // a^bint i = 0;for (i = 1; i <= nums.size() + 2; ++i) {tmp ^= i;}for (i = 0; i < nums.size(); ++i) {tmp ^= nums[i];}// 寻找xint x = 0;while (x < 32) {if (tmp & (1 << x)) {break;}++x;}// 分组得到a和bint a = 0;int b = 0;for (i = 1; i <= nums.size() + 2; ++i) {if (i & (1 << x)) {b ^= i;} else {a ^= i;}}for (i = 0; i < nums.size(); ++i) {if (nums[i] & (1 << x)) {b ^= nums[i];} else {a ^= nums[i];}}return {a, b};}
};

http://www.ppmy.cn/news/1562147.html

相关文章

Redis数据结构ZipList和QuickList原理解析

大家好&#xff0c;我是袁庭新。 在数据库的世界里&#xff0c;Redis 以其高效和灵活备受瞩目。而其中的 ZipList 和 QuickList 数据结构更是独具魅力。它们在内存管理和数据存储方面有着独特的设计理念&#xff0c;深入探究这些结构&#xff0c;能让我们更好地理解 Redis 的强…

(回溯法)leetcode39组合总和

第一个2开头&#xff0c;下面的子节点的集合元素均为2,5,3 但是在5开头&#xff0c;下面的子节点集合元素均为5,3 带着这个图的思路确定i和index的传递值 backtracking(i, nums,8,sum);用的是i而不是i1 // ConsoleApplication3.cpp : 此文件包含 "main" 函数。程序…

智能工厂的设计软件 应用场景的一个例子: 为AI聊天工具添加一个知识系统 之21 项目主页:基于资源的交互系统--以RESTful 风格设计构建 聊天窗口

本文要点 基于 RESTful 风格设计一个“为 AI 聊天工具添加一个知识树系统”的项目主页 本项目&#xff08;为AI聊天工具添加一个知识树系统&#xff09;的主页页面的三个页面版块( 注&#xff1a;一个项目的基础版本&#xff0c;它明确给出建模限制 what(where&#xff0c;ho…

嵌入式入门Day38

C Day1 第一个C程序C中的输入输出输出操作coutcin练习 命名空间使用方法自定义命名空间冲突问题 C对字符串的扩充C风格字符串的使用定义以及初始化C风格字符串与C风格字符串的转换C风格的字符串的关系运算常用的成员变量输入方法 布尔类型C对堆区空间使用的扩充作业 第一个C程序…

Selenium,一个Web自动化测试的Python库!

Selenium&#xff0c;一个Web自动化测试的Python库 大家好&#xff0c;我是景墨。今天咱们来聊聊一个超级实用的Python库&#xff1a;Selenium。这个库可以帮我们实现Web自动化测试&#xff0c;简直是测试工程师和爬虫开发者的神器&#xff01;保证学会了这个&#xff0c;你的…

Node.js JXcore 打包教程

Node.js JXcore 打包教程 介绍 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,它允许开发者使用 JavaScript 编写服务器端和网络应用程序。JXcore 是一个流行的 Node.js 发行版,它支持将 Node.js 应用程序打包成单一的可执行文件,使得部署和分发变得更加容易…

【C++习题】22.随机链表的复制

文章目录 题目&#xff1a;138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09;代码&#xff1a; 题目&#xff1a;138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 链接&#x1f517;&#xff1a;138. 随机链表的复制 - 力扣&#xff08;LeetCode&…

芯片详细讲解,从而区分CPU、MPU、DSP、GPU、FPGA、MCU、SOC、ECU

目录 芯片的概念结构 芯片的派系划分 通用芯片&#xff08;CPU&#xff0c;MPU&#xff0c;GPU&#xff0c;DSP&#xff09; 定制芯片&#xff08;FPGA&#xff0c;ASIC&#xff09; 芯片之上的集成&#xff08;MCU&#xff0c;SOC&#xff0c;ECU&#xff09; 软硬件的匹…