位运算算法:编程世界中的魔法符号

2024-06-17 10:36

本文主要是介绍位运算算法:编程世界中的魔法符号,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

✨✨✨学习的道路很枯燥,希望我们能并肩走下来!

文章目录

目录

文章目录

前言

一. 常见位运算总结

二、常见位运算题目

2.1 位1的个数

2.2 比特数记位(典型dp)

 2.3 汉明距离

2.4 只出现一次的数字(1) 

2.5 只出现一次的数字(2)  

 2.6 只出现一次的数字(3)

 2.7  判断字符是否为1

2.8 丢失的数字

 2.9 两整数之和

 2.10 消失的两个数字

总结


前言

本篇详细介绍了位运算算法的使用,让使用者了解位运算,而不是仅仅停留在表面, 文章可能出现错误,如有请在评论区指正,让我们一起交流,共同进步!


一. 常见位运算总结

二、常见位运算题目

2.1 位1的个数

191. 位1的个数 - 力扣(LeetCode)

 利用第七条特性:n&(n-1)干掉最后一个1,然后每次都用count++去统计,直到变成0

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

2.2 比特数记位(典型dp)

338. 比特位计数 - 力扣(LeetCode)

 思路1:每遍历一个数都用n&(n-1)去数他一共有多少个1,然后放ret数组中

class Solution {
public:vector<int> countBits(int n) {vector<int> ret(n+1);for(int i = 0 ;i<=n;i++){int m = i;int count = 0;while(m&(-m)){m&=(m-1);count++;}ret[i] = count;}return ret;}
};

 思路2:简单dp(前缀和 + 位运算

我们发现第i个位置的1的个数等于第i-1位置的1的个数+1

class Solution {
public:vector<int> countBits(int n) {vector<int> ret(n+1);for(int i = 1 ;i<=n;i++){ret[i] = ret[i&(i-1)] + 1;}return ret;}
};

 2.3 汉明距离

461. 汉明距离 - 力扣(LeetCode)

        利用异或相同为0相异为1的特点,x和y异或后不一样的位都会变成1,这个时候再用n&(n-1)去统计1个个数,即为这两个数字的汉明距离 

class Solution {
public:int hammingDistance(int x, int y) {//异或的特点,相同为0,相异为1     然后再利用n&(n-1)统计1的个数int n=x^y;int count=0;while(n){n&=(n-1);++count;}return count;}
};

2.4 只出现一次的数字(1) 

136. 只出现一次的数字 - 力扣(LeetCode) 

 思路:利用异或的性质,出现两次的数异或后为0,出现一次的数异或0还是本身 

class Solution {
public:int singleNumber(vector<int>& nums) {int value = 0;for(auto &e : nums){value^=e;}return value;}
};

2.5 只出现一次的数字(2)  

137. 只出现一次的数字 II - 力扣(LeetCode) 

具体地,考虑答案的第 iii 个二进制位(iii 从 000 开始编号),它可能为 000 或 111。对于数组中非答案的元素,每一个元素都出现了 333 次,对应着第 iii 个二进制位的 333 个 000 或 333 个 111,无论是哪一种情况,它们的和都是 333 的倍数(即和为 000 或 333)。因此:

答案的第 iii 个二进制位就是数组中所有元素的第 iii 个二进制位之和除以 333 的余数。 

class Solution {
public:int singleNumber(vector<int>& nums) {int ans = 0;for (int i = 0; i < 32; ++i) {// 统计该每个数字第i个比特位为1的总数int total = 0;for (int num: nums) {total += ((num >> i) & 1);}// 如果total能够被3整除,说明只出现一次的数字在该位置上一定是0// 否则在该位置上一定是1if (total % 3) {ans |= (1 << i);}}return ans;}
};

 2.6 只出现一次的数字(3)

260. 只出现一次的数字 III - 力扣(LeetCode) 

 

class Solution {
public:vector<int> singleNumber(vector<int>& nums) {unsigned int temp=0;//遇到INT_MIN会溢出,10000……00for(int num:nums) temp^=num;int x=temp&(-temp);//x拿到最后一个1,即两个数不同的地方//int x= (temp == temp ? temp : temp & (-temp));int type1=0,type2=0;for(int num:nums) if(num&x) value1^=num; else value2^=num;return {value,value};}
};

一般解法:

class Solution {
public:vector<int> singleNumber(vector<int>& nums) {sort(nums.begin(), nums.end());vector<int> res;int i = 0;for (; i < nums.size() - 1; ) {if (nums[i] == nums[i + 1]) {i += 2;} else {res.push_back(nums[i]);i += 1;}}if (i < nums.size()) {res.push_back(nums[i]);}return res;     }
};

 2.7  判断字符是否为1

面试题 01.01. 判定字符是否唯一 - 力扣(LeetCode) 

class Solution {
public:bool isUnique(string astr) {// 利用鸽巢原理做优化if(astr.size()>26) return false;int bitMap = 0;for(auto& ch : astr){int i = ch - 'a';// 先判断字符是否出现过if((bitMap>>i) & 1 == 1) return false;// 将当前字符加入到位图中bitMap |= (1<<i);}return true;}
};

2.8 丢失的数字

268. 丢失的数字 - 力扣(LeetCode) 

 

思路1:高斯公式

 

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

思路2:异或运算 

class Solution {
public:int missingNumber(vector<int>& nums) {int n = nums.size();int ret = 0;for(auto& e : nums) ret^=e;for(int i = 0;i<=n;i++) ret^=i;return ret;}
};

 2.9 两整数之和

371. 两整数之和 - 力扣(LeetCode) 

 

class Solution {
public:int getSum(int a, int b) {while(b != 0){int x = a^b; //先算出无进位相加的结果unsigned int carry = (unsigned int)(a&b)<<1; //算出进位,//要考虑-1,因为-1的右移操作是没有定义的a = x;b = carry;}return a;}
};

 2.10 消失的两个数字

面试题 17.19. 消失的两个数字 - 力扣(LeetCode) 

 

class Solution {
public:vector<int> missingTwo(vector<int>& nums) {//1.将所有的数异或在一起int tmp = 0;for(auto& e : nums)tmp^=e;for(int i = 1;i<=nums.size()+2;i++)tmp^=i;//2. 找a,b中比特位不同的那一位int x = tmp&(-tmp);// 3. 根据比特位不同的那一位,划分成两类来异或int a = 0, b = 0;for(auto& e : nums){if(e&x) a^=e;else    b^=e;}for(int i=1;i<=nums.size()+2;++i){if(i&x) a^=i;  else  b^=i;}return {a,b};}
};

总结

✨✨✨各位读友,本篇分享到内容是否更好的让你理解位运算算法,如果对你有帮助给个👍赞鼓励一下吧!!
🎉🎉🎉世上没有绝望的处境,只有对处境绝望的人。
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!

这篇关于位运算算法:编程世界中的魔法符号的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1069202

相关文章

零基础STM32单片机编程入门(一)初识STM32单片机

文章目录 一.概要二.单片机型号命名规则三.STM32F103系统架构四.STM32F103C8T6单片机启动流程五.STM32F103C8T6单片机主要外设资源六.编程过程中芯片数据手册的作用1.单片机外设资源情况2.STM32单片机内部框图3.STM32单片机管脚图4.STM32单片机每个管脚可配功能5.单片机功耗数据6.FALSH编程时间,擦写次数7.I/O高低电平电压表格8.外设接口

16.Spring前世今生与Spring编程思想

1.1.课程目标 1、通过对本章内容的学习,可以掌握Spring的基本架构及各子模块之间的依赖关系。 2、 了解Spring的发展历史,启发思维。 3、 对 Spring形成一个整体的认识,为之后的深入学习做铺垫。 4、 通过对本章内容的学习,可以了解Spring版本升级的规律,从而应用到自己的系统升级版本命名。 5、Spring编程思想总结。 1.2.内容定位 Spring使用经验

代码随想录算法训练营:12/60

非科班学习算法day12 | LeetCode150:逆波兰表达式 ,Leetcode239: 滑动窗口最大值  目录 介绍 一、基础概念补充: 1.c++字符串转为数字 1. std::stoi, std::stol, std::stoll, std::stoul, std::stoull(最常用) 2. std::stringstream 3. std::atoi, std

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

【第十三课】区域经济可视化表达——符号表达与标注

一、前言 地图最直接的表达就是使用符号表达。使用符号可以把简单的点线面要 素渲染成最直观的地理符号,提高地图的可读性。只要掌握了 ArcGIS 符号制 作的技巧,分析符号并总结出规则,就可以制作符合要求的地图+符号。 (一)符号的选择与修改 符号的选择在制图中至关重要,使用符号选择器对话框可从多个可用样式 中选择符号,并且每个符号都有一个标签用来描述其图形特征,如颜色或类型, 利用这些标签可

【网络安全的神秘世界】搭建dvwa靶场

🌝博客主页:泥菩萨 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 下载DVWA https://github.com/digininja/DVWA/blob/master/README.zh.md 安装DVWA 安装phpstudy https://editor.csdn.net/md/?articleId=1399043

C语言入门系列:探秘二级指针与多级指针的奇妙世界

文章目录 一,指针的回忆杀1,指针的概念2,指针的声明和赋值3,指针的使用3.1 直接给指针变量赋值3.2 通过*运算符读写指针指向的内存3.2.1 读3.2.2 写 二,二级指针详解1,定义2,示例说明3,二级指针与一级指针、普通变量的关系3.1,与一级指针的关系3.2,与普通变量的关系,示例说明 4,二级指针的常见用途5,二级指针扩展到多级指针 小结 C语言的学习之旅中,二级

大林 PID 算法

Dahlin PID算法是一种用于控制和调节系统的比例积分延迟算法。以下是一个简单的C语言实现示例: #include <stdio.h>// DALIN PID 结构体定义typedef struct {float SetPoint; // 设定点float Proportion; // 比例float Integral; // 积分float Derivative; // 微分flo

LeetCode 算法:二叉树的中序遍历 c++

原题链接🔗:二叉树的中序遍历 难度:简单⭐️ 题目 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root = [1,null,2,3] 输出:[1,3,2] 示例 2: 输入:root = [] 输出:[] 示例 3: 输入:root = [1] 输出:[1] 提示: 树中节点数目在范围 [0, 100] 内 -100 <= Node.