【优选算法必刷100题:专题五】(位运算算法)第033~38题:判断字符是否唯一、丢失的数字、两整数之和、只出现一次的数字 II、消失的两个数字

【优选算法必刷100题:专题五】(位运算算法)第033~38题:判断字符是否唯一、丢失的数字、两整数之和、只出现一次的数字 II、消失的两个数字

在这里插入图片描述


🎬 个人主页艾莉丝努力练剑
专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录
Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:

在这里插入图片描述

🎬艾莉丝的算法专栏简介:

在这里插入图片描述

文章目录


在这里插入图片描述

常见位运算总结

1 ~> 刷前必刷题单

干掉一个数(n)二进制表示中最右侧的1:
classSolution{public:inthammingWeight(int n){int count =0;while(n){ n &=(n -1); count++;}return count;}};
// 奇偶性动态规划// class Solution {// public:// vector<int> countBits(int n) {// vector<int> ans(n + 1,0);// for(int i = 1;i < n + 1;i++)// {// ans[i] = ans[i >> 1] + (i & 1);// }// return ans;// }// };// 汉明重量问题解法classSolution{public: vector<int>countBits(int n){ vector<int>ans(n +1);for(int i =1;i < n +1;i++){int count =0;int nums = i;while(nums){ nums &=(nums -1); count++;} ans[i]= count;}return ans;}};
// 干掉一个数二进制位中表示最右侧的1classSolution{public:inthammingDistance(int x,int y){int val = x ^ y;int count =0;while(val){ val &=(val -1); count++;}return count;}};
异或(^)运算的运算律相关的算法题:
classSolution{public:intsingleNumber(vector<int>& nums){int result =0;int i =0;while(i < nums.size()){ result ^= nums[i]; i++;}return result;}};
classSolution{public: vector<int>singleNumber(vector<int>& nums){ vector<int>ans(2,0);int result =0;int i =0;while(i < nums.size()){ result ^= nums[i]; i++;}unsignedint val = result &(-(unsignedint)result); i =0;// 重置iwhile(i < nums.size()){if(nums[i]& val){ ans[0]^= nums[i];}else{ ans[1]^= nums[i];} i++;}return ans;}};

2 ~> 博主手记

在这里插入图片描述
在这里插入图片描述

033 判断字符是否唯一

力扣链接:面试题 01.01. 判定字符是否唯一

题目描述:

在这里插入图片描述

​1.1 解法(位图的思想):

利用「位图」的思想,每一个【比特位】代表一个【字符】,一个int类型的变量的32位足够表示所有的小写字母。比特位里面如果是0,表示这个字符没有出现过。比特位里面的值是1,表示该字符出现过。

那么我们就可以用一个【整数】来充当【哈希表】。

1.2 算法实现

classSolution{public:boolisUnique(string astr){// 利用鸽巢原理做优化if(astr.size()>26)returnfalse;// 搞定位图int bitMap =0;// 遍历字符串for(auto ch : astr){int i = ch -'a';// 先把重复的字符处理一下if((bitMap >> i)&1==1)returnfalse;// 说明字符没有出现过,添加到位图中 bitMap |=1<< i;}returntrue;}};

1.3 博主手记

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下手记的推导过程!最好做题的过程中自己也推导一遍!!!自己能够推导很重要!
在这里插入图片描述

034 丢失的数字

力扣链接:268. 丢失的数字

题目描述:

在这里插入图片描述

2.1 解法:位运算

设数组的大小为n,那么缺失之前的数就是[0 , n],数组中是在[0,n]中缺失一个数形成的序列。

如果我们把数组中的所有数,以及[0 , n]中的所有数全部【异或】在一起,那么根据【异或】运算的【消消乐】规律,最终的异或结果应该就是缺失的数。

2.2 算法实现

classSolution{public:intmissingNumber(vector<int>& nums){// 用ret表示确实的那个数字int ret =0;// 把数组中的数异或在一起for(auto x : nums) ret ^= x;// 把0~n中的数异或在一起for(int i =0;i <= nums.size();i++) ret ^= i;return ret;}};
在这里插入图片描述

2.3 博主手记

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下手记的推导过程!最好做题的过程中自己也推导一遍!!!自己能够推导很重要!
在这里插入图片描述

035 两整数之和

力扣链接:371. 两整数之和

题目描述:

在这里插入图片描述

3.1 位运算解法的算法思路

  • 异或^运算本质是【无进位加法】;
  • 按位与&操作能够得到【进位】;
  • 然后一直循环进行,直到【进位】变成0为止。

3.2 算法实现

classSolution{public:intgetSum(int a,int b){while(b !=0)// 一直重复这个操作{int x = a ^ b;// 先算出无进位相加的结果unsignedint carry =(unsignedint)(a & b)<<1;// 算出算出进位// 这里用unsigned int是考虑到a & b如果是-1的话,此时左移操作是没有定义的,用这种方式处理一下-1的情况(把-1当成无符号的整数) a = x;// 把无进位相加结果给a b = carry;// 把进位相加结果给b}return a;}};
在这里插入图片描述
笔试场上可以不讲武德,面试官不看,而且代码也是会通过的:
classSolution{public:intgetSum(int a,int b){return a + b;}};

3.3 博主手记

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下手记的推导过程!最好做题的过程中自己也推导一遍!!!自己能够推导很重要!
在这里插入图片描述

036 只出现一次的数字 II

力扣链接:137. 只出现一次的数字 II

题目描述:

在这里插入图片描述

4.1 解法思路:比特位计数

设要找的数位ret

由于整个数组中,需要找的元素只出现了【一次】,其余的数都出现的【三次】,因此我们可以根据所有数的【某一个比特位】的总和%3的结果,快速定位到ret的【一个比特位上】的值是0还是1。

这样,我们通过ret的每一个比特位上的值,就可以将ret给还原出来。

4.2 算法实现

classSolution{public:intsingleNumber(vector<int>& nums){int ret =0;for(int i =0;i <32;i++)// 依次去修改 ret 中的每一位{int sum =0;for(int x : nums)// 计算 nums 中所有的数的第 i 位的和if(((x >> i)&1)==1) sum++; sum %=3;if(sum ==1) ret |=(1<< i);}return ret;}};
在这里插入图片描述

4.3 博主手记

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下手记的推导过程!最好做题的过程中自己也推导一遍!!!自己能够推导很重要!
在这里插入图片描述

037 消失的两个数字

力扣链接:面试题 17.19. 消失的两个数字

题目描述:

在这里插入图片描述

5.1 解法:位运算

本题就是268. 丢失的数字 + 260. 只出现一次的数字 III组合起来的题。

先将数组中的数和[1 , n + 2]区间内的所有数【异或】在一起,问题就变成了:有两个数出现了【一次】,其余所有的数出现了【两次】。进而变成了260. 只出现一次的数字 III这道题。

5.2 算法实现

classSolution{public: vector<int>missingTwo(vector<int>& nums){// 1、将所有的数异或在一起int tmp =0;for(auto x : nums) tmp ^= x;// 异或原数组中的数// 异或1 ~ Nfor(int i =1;i <= nums.size()+2;i++) tmp ^= i;// 2、找出a,b中比特位不同的那一位int diff =0;while(1){if(((tmp >> diff)&1)==1)break;else diff++;}// 3、根据diff位的不同,将所有的数划分为两类来异或int a =0,b =0;for(int x : nums)if(((x >> diff)&1)==1) b ^= x;else a ^= x;for(int i =1;i <= nums.size()+2;i++)if(((i >> diff)&1)==1) b ^= i;else a ^= i;return{a,b};}};
在这里插入图片描述

5.3 博主手记

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下手记的推导过程!最好做题的过程中自己也推导一遍!!!自己能够推导很重要!
在这里插入图片描述

结尾

uu们,本文的内容到这里就全部结束了,艾莉丝再次感谢您的阅读!

结语:希望对学习算法相关内容的uu有所帮助,不要忘记给博主“一键四连”哦!

往期回顾:

【优选算法必刷100题】第031~32题(前缀和算法):连续数组、矩阵区域和

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡૮₍ ˶ ˊ ᴥ ˋ˶₎ა

Read more

LeetCode128:哈希集合巧解最长连续序列

LeetCode128:哈希集合巧解最长连续序列

一、题目回顾 LeetCode 128 题「最长连续序列」是一道中等难度的数组题,核心要求如下:给定一个未排序的整数数组 nums,找出其中数字连续的最长序列(不要求序列元素在原数组中连续)的长度,且必须设计时间复杂度为 O (n) 的算法。 示例直观理解: * 输入 nums = [100,4,200,1,3,2],输出 4(最长序列是 [1,2,3,4]); * 输入 nums = [0,3,7,2,5,8,4,6,0,1],输出 9(完整连续序列 0-8)。 二、

By Ne0inhk
一文彻底搞清楚数据结构之快速排序和归并排序的深入优化

一文彻底搞清楚数据结构之快速排序和归并排序的深入优化

🔥承渊政道:个人主页 ❄️个人专栏: 《C语言基础语法知识》《数据结构与算法初阶》 ✨逆境不吐心中苦,顺境不忘来时路!🎬 博主简介: 前言:前面小编已经介绍八大排序算法的基本思想和实现方法!但关于其中的快速排序和归并排序还有一些细节可以优化!接下来跟着小编来看看快速排序和归并排序的深入优化,学习一下优化完之后,具体在实际中的应用!废话不多说,下面跟着小编的节奏🎵一起学习吧! 目录 * 1.快速排序性能的关键点分析 * 1.1三路划分算法思想讲解 * 1.2hoare和lomuto和三路划分单趟排序代码分析 * 1.3三种快排单趟排序运⾏结果分析 * 2.排序数组OJ题 * 2.1lomuto的快速排序跑排序数组OJ题 * 2.2hoare的快速排序跑排序数组OJ题 * 2.3三路划分的快速排序跑排序数组OJ题 * 2.4introsort的快速排序跑排序数组OJ题 * 3.外排序介绍 * 3.1创建随机数据⽂件的代码 * 3.2⽂件归并排序思路分析 * 3.3⽂件归并排序代码实现 * 3.4非递归版

By Ne0inhk
LeetCode 141题:环形链表的艺术与科学

LeetCode 141题:环形链表的艺术与科学

🌟 LeetCode 141题:环形链表的艺术与科学 * 🌀 环形链表:当数据开始循环舞蹈 * 🔍 解法一:哈希表法 - 记忆的艺术 * 解题思路 * 性能分析 * 🏃‍♂️ 解法二:快慢指针法 - 龟兔赛跑的智慧 * 解题思路 * 性能优势 * 💻 代码实现与调试心得 * 🌈 思维与实现的分离 * 🎯 总结 因为想更好地为义父义母大佬服务,本文 Bilibili 视频地址 🌀 环形链表:当数据开始循环舞蹈 在计算机科学的世界里,链表是一种优雅而基础的数据结构。正常链表如同一条笔直的小路,从起点(head)出发,每个节点指向下一个节点,最终以空指针(nullptr)作为终点,标志着旅程的结束。 Head Node1 Node2 Node3 nullptr 然而,环形链表则打破了这种线性规则,它更像是一个神秘的莫比乌斯环,没有真正的终点。链表的某个节点不再指向空,而是指向链表中已经存在的另一个节点,形成了一个无尽的循环。 Head

By Ne0inhk
代码随想录算法训练营Day 1 | 二分:LeetCode704二分查找、35搜索插入位置、34查找元素第一个和最后一个位置 | 双指针:27移除元素、977有序数组的平方

代码随想录算法训练营Day 1 | 二分:LeetCode704二分查找、35搜索插入位置、34查找元素第一个和最后一个位置 | 双指针:27移除元素、977有序数组的平方

704.二分查找 模板题 题目链接:https://leetcode.cn/problems/binary-search/代码随想录题解: 704. 二分查找 | 代码随想录 状态:完全掌握三种模板 “一只会code的小金鱼”的分界线思路(左开右开)和卡哥的思路(左闭右开)(左闭右闭)         这题是模板题,用卡哥的思路很快就写出来了,而且很好记忆;         我给二分模板定了三要素进行记忆,1.左右初始化;2.while()条件;3.mid是否±1。         以前自己写二分老是会忘记while()的条件是left<right还是left<=right?什么时候用left=middle+1还是left=middle,right=middle-1还是right=middle?初始化该用left=0还是left=-1,right=

By Ne0inhk