【剑指offer|图解|位运算】训练计划VI+撞色搭配
🌈个人主页:聆风吟
🔥系列专栏:数据结构、剑指offer每日一练
🔖少年有梦不应止于心动,更要付诸行动。
文章目录
- 一. ⛳️训练计划VI(题目难度:中等)
- 1.1 题目
- 1.2 示例
- 1.3 限制
- 1.4 解题思路
- 1.5 c++代码
- 二. ⛳️撞色搭配(题目难度:中等)
- 2.1 题目
- 2.2 示例
- 2.3 限制
- 2.4 解题思路
- 2.5 c++代码
- 📝全文总结
一. ⛳️训练计划VI(题目难度:中等)
⌈ 在线OJ链接,可以转至此处自行练习 ⌋
1.1 题目
教学过程中,教练示范一次,学员跟做三次。该过程被混乱剪辑后,记录于数组 actions,其中 actions[i] 表示做出该动作的人员编号。请返回教练的编号。
1.2 示例
输入: actions = [5, 7, 5, 5]
输出: 7
1.3 限制
- 1 <= actions.length <= 10000
- 1 <= actions[i] < 2^31
1.4 解题思路
- 📗使用 与运算 我们可以获取数字num二进制位的最右边的一位。
- 📕配合 右移操作 ,我们可以从低位到高位依次获取num的每一位二进制的值。
- 📘建立一个长度位32的数组,使用上面方法存放所有数字各二进制 1 出现的次数之和。
- 📙将 count 各元素对 3 求余,则结果为 “只出现一次的数字” 的各二进制位。
- 📓利用 左移 和 或运算,可将数组中的二进制位恢复到数字ret上,然后返回ret即可。
1.5 c++代码
class Solution {
public:
int trainingPlan(vector<int>& actions) {
int count[32] = { 0 };//用来记录所有数字各二进制 1 出现的次数之和
//开始统计所有数字各二进制 1 出现的次数之和
for(int i = 0; i < actions.size(); i++){
for(int j = 0; j < 32; j++){
count[j] += (actions[i] >> j) & 1;
}
}
int ret = 0;//记录只出现一次的数字
int m = 3;
//将数组中的二进制位恢复到数字ret上
for(int i = 31; i >= 0; i--){
ret <<= 1;
ret |= count[i] % m;
}
return ret;
}
};
二. ⛳️撞色搭配(题目难度:中等)
⌈ 在线OJ链接,可以转至此处自行练习 ⌋
2.1 题目
整数数组 sockets 记录了一个袜子礼盒的颜色分布情况,其中 sockets[i] 表示该袜子的颜色编号。礼盒中除了一款撞色搭配的袜子,每种颜色的袜子均有两只。请设计一个程序,在时间复杂度 O(n),空间复杂度O(1) 内找到这双撞色搭配袜子的两个颜色编号。
2.2 示例
输入: sockets = [4, 5, 2, 4, 6, 6]
输出: [2,5] 或 [5,2]
2.3 限制
- 2 <= sockets.length <= 10000
2.4 解题思路
拓展知识: 异或运算有个重要的性质,就是两个相同的值异或结果为0,即对任意整数 a 有 a ⊕ a = 0。并且异或运算满足交换律 a ⊕ b = b ⊕ a。
-
📗首先让sockets中的所有元素进行异或,并将结果赋给sum。
-
📕根据
异或运算
定义,若整数 x⊕y 某位二进制位为 1 ,则 x 和 y 的此二进制位一定不同。
-
📘因此,我们可以通过
与运算
从右向左循环判断,获取整数 x⊕y 首位为 1 的位置 ,将其记录于 m 中。
-
📙将数组sockets中所有元素二进制均右移m位,并
&1
判断数字是否相同,即可将数组 sockets 拆分为分别包含5
和2
的两个子数组,分别对两个子数组进行异或即可得出结果。
2.5 c++代码
class Solution {
public:
vector<int> sockCollocation(vector<int>& sockets) {
int sum = 0;//sockets中的所有元素进行异或,并将结果赋给sum
for(int i = 0; i < sockets.size(); i++){
sum ^= sockets[i];
}
int pos = 0;//记录sum二进制位最右边一个 1 的位数
for(int i = 0; i < 32; i++){
if((sum>>i) & 1){
pos = i;
break;
}
}
//将拆分子数组,让子数组进行异或,求出说需要的值。
int x = 0;
int y = 0;
for(int i = 0; i < sockets.size(); i++){
if((sockets[i] >> pos) & 1)
x ^= sockets[i];
else
y ^= sockets[i];
}
return {x, y};
}
};
📝全文总结
本文主要讲解:
今天的干货分享到这里就结束啦!如果觉得文章还可以的话,希望能给个三连支持一下,聆风吟的主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的最大动力!