当前位置: 首页 > article >正文

【剑指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 解题思路

  1. 📗使用 与运算 我们可以获取数字num二进制位的最右边的一位。
    在这里插入图片描述
  2. 📕配合 右移操作 ,我们可以从低位到高位依次获取num的每一位二进制的值。
  3. 📘建立一个长度位32的数组,使用上面方法存放所有数字各二进制 1 出现的次数之和。
    在这里插入图片描述
  4. 📙将 count 各元素对 3 求余,则结果为 “只出现一次的数字” 的各二进制位。
    在这里插入图片描述

  5. 📓利用 左移或运算,可将数组中的二进制位恢复到数字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。

  1. 📗首先让sockets中的所有元素进行异或,并将结果赋给sum。
    在这里插入图片描述

  2. 📕根据异或运算定义,若整数 x⊕y 某位二进制位为 1 ,则 x 和 y 的此二进制位一定不同。
    在这里插入图片描述

  3. 📘因此,我们可以通过与运算从右向左循环判断,获取整数 x⊕y 首位为 1 的位置 ,将其记录于 m 中。
    在这里插入图片描述

  4. 📙将数组sockets中所有元素二进制均右移m位,并&1判断数字是否相同,即可将数组 sockets 拆分为分别包含 52 的两个子数组,分别对两个子数组进行异或即可得出结果。
    在这里插入图片描述

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};
    }
};


📝全文总结

本文主要讲解:

     今天的干货分享到这里就结束啦!如果觉得文章还可以的话,希望能给个三连支持一下,聆风吟的主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的最大动力!
在这里插入图片描述


http://www.kler.cn/a/158583.html

相关文章:

  • 不完全微分PID控制算法
  • C# 异常处理、多个异常、自定义异常处理
  • 鸿蒙next版开发:拍照实现方案(ArkTS)
  • 39.十进制数转化为二进制数 C语言
  • 深入解析大带宽服务器:性能优势与选择指南
  • 【JavaEE初阶 — 多线程】wait() notify()
  • Java的严格计算部分
  • 解决ant-design-vue中Select组件v-model值为空字符串不显示placeholder的bug
  • windows使用YOLOv8训练自己的模型(0基础保姆级教学)
  • 代码随想录二刷 | 栈与队列 | 用队列实现栈
  • 华容道问题求解第一部分_思路即方案设计
  • 掌握反转链表的艺术:LeetCode 206 深入解析与优化 - 双指针与递归方法精讲
  • 关于队列的简单理解
  • JS--异步的日常用法
  • 在vscode下将ipynb文件转成markdown(.md文件)的方法
  • 12.4 C++ 作业
  • 【win32_003】不同字符集下的通用字符串语法TCHAR、TEXT、PTSTR、PCTSTR
  • 有趣的代码——有故事背景的程序设计3
  • 驱动模块--内核模块
  • Qt 布局讲解及举例
  • 打破界限:SQL数据库水平扩展的8大挑战与机遇
  • 【开源】基于JAVA的医院门诊预约挂号系统
  • (C++)有效三角形的个数--双指针法
  • 推荐6款本周 火火火火 的开源项目
  • SpringBoot学习笔记-实现微服务:匹配系统(下)
  • C语言初学4:C 存储类