算法思想之位运算(一)

news2025/4/16 14:00:53

欢迎拜访:雾里看山-CSDN博客
本篇主题:算法思想之位运算(一)
发布时间:2025.4.12
隶属专栏:算法

在这里插入图片描述

目录

  • 算法介绍
    • 六大基础位运算符
    • 常用模板总结
  • 例题
    • 位1的个数
      • 题目链接
      • 题目描述
      • 算法思路
      • 代码实现
    • 比特位计数
      • 题目链接
      • 题目描述
      • 算法思路
      • 代码实现
    • 只出现一次的数字
      • 题目链接
      • 题目描述
      • 算法思路
      • 代码实现
    • 只出现一次的数字 II
      • 题目链接
      • 题目描述
      • 算法思路
      • 代码实现
    • 只出现一次的数字 III
      • 题目链接
      • 题目描述
      • 算法思路
      • 代码实现

算法介绍

位运算(Bit Manipulation)是算法中的高效技巧,通过直接操作二进制位实现快速计算和优化存储

六大基础位运算符

运算符符号描述示例
按位与&两数二进制位同为1时结果为15 & 3 → 1 (101 & 011 = 001)
按位或|任一位为1时结果为15 | 3→7 (101 | 011 = 111)
按位异或^两数位不同时结果为1 ,无进位相加5 ^ 3 → 6 (101 ^ 011 = 110)
按位取反~0变1,1变0~5 → -6(补码表示)
左移<<左移指定位数,低位补05 << 1 → 10 (101→1010)
右移>>右移指定位数,高位补符号位(算术右移)-5 >> 1 → -3

常用模板总结

功能代码模板
判断奇偶x & 1 → 1为奇,0为偶
取最低位的1x & (-x)
消去最低位的1x & (x - 1)
异或交换变量a ^= b; b ^= a; a ^= b;
生成所有子集for (mask = 0; mask < (1 << n); mask++)
快速幂右移指数,逐位判断累乘

例题

位1的个数

题目链接

191. 位1的个数

题目描述

给定一个正整数 n,编写一个函数,获取一个正整数的二进制形式并返回其二进制表达式中 设置位 的个数(也被称为汉明重量)。

示例 1

输入:n = 11
输出:3
解释:输入的二进制串 1011 中,共有 3 个设置位。

示例 2

输入:n = 128
输出:1
解释:输入的二进制串 10000000 中,共有 1 个设置位。

示例 3

输入:n = 2147483645
输出:30
解释:输入的二进制串 1111111111111111111111111111101 中,共有 30 个设置位。

提示

  • 1 <= n <= 231 - 1

进阶
如果多次调用这个函数,你将如何优化你的算法?

算法思路

直接使用模板中消去最低位的1,直到变量为零,用一个变量计算次数即可。

代码实现

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

在这里插入图片描述

比特位计数

题目链接

338. 比特位计数

题目描述

给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

示例 1

输入:n = 2
输出:[0,1,1]
解释
0 --> 0
1 --> 1
2 --> 10

示例 2

输入:n = 5
输出:[0,1,1,2,1,2]
解释
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101

提示

  • 0 <= n <= 105

进阶

  • 很容易就能实现时间复杂度为 O(n log n) 的解决方案,你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗?
  • 你能不使用任何内置函数解决此问题吗?(如,C++ 中的 __builtin_popcount

算法思路

遍历一遍数组,对于每个数,直接使用模板中消去最低位的1,直到变量为零,用一个变量计算次数即可。

代码实现

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

在这里插入图片描述

只出现一次的数字

题目链接

136. 只出现一次的数字

题目描述

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

示例 1
输入:nums = [2,2,1]
输出:1

示例 2

输入:nums = [4,1,2,1,2]
输出:4

示例 3

输入:nums = [1]
输出:1

提示

  • 1 <= nums.length <= 3 * 104
  • -3 * 104 <= nums[i] <= 3 * 104
  • 除了某个元素只出现一次以外,其余每个元素均出现两次。

算法思路

  1. 任何数和 0 做异或运算,结果仍然是原来的数,即 a^0=a
  2. 任何数和其自身做异或运算,结果是 0,即 a^a=0
  3. 异或运算满足交换律和结合律,即 a^b^a=b^a^a=b^(a^a)=b^0=b

代码实现

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

在这里插入图片描述

只出现一次的数字 II

题目链接

137. 只出现一次的数字 II

题目描述

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。

示例 1

输入:nums = [2,2,3,2]
输出:3

示例 2

输入:nums = [0,1,0,1,0,1,99]
输出:99
提示

  • 1 <= nums.length <= 3 * 104
  • -231 <= nums[i] <= 231 - 1
  • nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次

算法思路

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

代码实现

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int num = 0;
        for(int i = 0; i < 32; i++)
        {
            int count = 0;
            for(auto n : nums)
            {
                count += ((n>>i)&1);
            }
            if(count % 3)
                num |= (1<<i);
        }
        return num;
    }
};

在这里插入图片描述

只出现一次的数字 III

题目链接

260. 只出现一次的数字 III

题目描述

给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。

示例 1

输入:nums = [1,2,1,3,2,5]
输出:[3,5]
解释:[5, 3] 也是有效的答案。

示例 2

输入:nums = [-1,0]
输出:[-1,0]

示例 3

输入:nums = [0,1]
输出:[1,0]

提示

  • 2 <= nums.length <= 3 * 104
  • -231 <= nums[i] <= 231 - 1
    除两个只出现一次的整数外,nums 中的其他数字都出现两次

算法思路

出现两次的数异或操作后会抵消,而两个不相等的数异或后的结果,必有一个比特位是为1的,我们根据这个比特位将所有数据分为两组。即可得出这两个数。

  • 将所有数进行异或操作,异或后的结果中不为零的比特位即为区分点
  • 通过找出的区分点,找出两个数。

代码实现

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        int num = 0;
        for(auto n : nums)
        {
            num ^= n;
        }
        // 通过最低位的1将数据分为两组
        int l = (num==INT_MIN ? num : num&(-num));
        int sum1 = 0, sum2 = 0;
        for(auto n : nums)
        {
            if(n & l)
                sum1^=n;
            else
                sum2^=n;
        }
        return {sum1, sum2};
    }
};

在这里插入图片描述

⚠️ 写在最后:以上内容是我在学习以后得一些总结和概括,如有错误或者需要补充的地方欢迎各位大佬评论或者私信我交流!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2336005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【基于Servlet技术处理表单】

文章目录 一、实验背景与目的二、实验设计与实现思路1. 功能架构2. 核心代码实现3. 测试用例 总结 一、实验背景与目的 本次实验旨在深入理解Servlet工作原理&#xff0c;掌握JSP与Servlet的协同开发&#xff0c;实现前端表单与后端数据处理的交互。具体目标包括&#xff1a;设…

[OS] mmap | fd是什么 | inode机制 | vfs封装

Linux 下一切皆文件 * 统统抽象为文件&#xff0c;系统封装一层结构体之后&#xff0c;通过指针来访问 * 文章后面的 几个思考题都挺好的 * 后面涉及到的inode 机制&#xff0c;去年暑假的这篇文章&#xff0c;有详细的记录到过 【Linux】(26) 详解磁盘与文件系统&#xff1a;从…

STL详解 - vector的模拟实现

目录 一、整体设计 1.1 核心结构 1.2 迭代器实现 二、核心接口实现 2.1 构造函数系列 &#x1f334;默认构造 &#x1f334;迭代器范围构造 &#x1f334;元素填充构造 2.2 拷贝控制 &#x1f335;拷贝构造函数 &#x1f335;赋值运算符&#xff08;现代写法&#xf…

C++第三方库【JSON】nlohman/json

文章目录 优势使用API从文件中读取json从json文本创建json对象直接创建并操作json对象字符串 <> json对象文件流 <> json对象从迭代器读取像使用STL一样的访问STL容器转化为 json数组STL容器 转 json对象自定义类型转化为 json对象 限制 优势 直观的语法&#xff…

超细的ollama下载以及本地部署deepseek项目

Ollama 是一个开源的本地化大语言模型&#xff08;LLM&#xff09;运行和部署工具&#xff0c;专注于让开发者能够快速、高效地在本地运行和管理各种开源大语言模型&#xff08;如 LLaMA、Mistral、GPT 系列等&#xff09;。它提供了一个统一的接口&#xff0c;简化了模型下载、…

【Sequelize】关联模型和孤儿记录

一、关联模型的核心机制 1. 关联类型与组合规则 • 基础四类型&#xff1a; • hasOne&#xff1a;外键存储于目标模型&#xff08;如用户档案表存储用户ID&#xff09; • belongsTo&#xff1a;外键存储于源模型&#xff08;如订单表存储用户ID&#xff09; • hasMany&…

Sentinel实战教程:流量控制与Spring Boot集成

Sentinel实战教程:流量控制与Spring Boot集成 1. Sentinel简介与核心概念 1.1 什么是Sentinel? Sentinel是阿里巴巴开源的流量控制组件,主要用于微服务架构中的流量防护。它通过限流、熔断、热点防护等机制,帮助系统在高并发场景下保持稳定运行。 1.2 核心功能与术语 流…

循环神经网络 - 扩展到图结构之递归神经网络

本文我们来学习递归神经网络(Recursive Neural Network&#xff0c;RecNN)&#xff0c;其是循环神经网络在有向无循环图上的扩展 。 递归神经网络是一类专门设计来处理具有层次结构或树形结构的数据的神经网络模型。它与更常见的循环神经网络&#xff08;Recurrent Neural Net…

Maven超级详细安装部署

1.到底什么是Maven&#xff1f;搞清楚这个 Maven 是一个项目管理工具&#xff0c;主要用于 Java 项目的构建、依赖管理和文档生成。 它基于项目对象模型&#xff08;POM&#xff09;&#xff0c;通过 pom.xml 文件定义项目的配置。 &#xff08;简单说破&#xff1a;就是工程…

电机控制-隆博戈观测器(Luenberger state observer)

本文围绕基于无传感器控制策略的状态观测器展开&#xff0c;介绍其在电机领域的应用、原理、性能表现及无传感器驱动的优劣&#xff1a; 应用场景&#xff1a;适用于燃油泵、风扇等大量固定转速和低成本应用场景。工作原理&#xff1a;状态观测器利用完整的电机微分模型&#…

RK3506+net9+VS2022跨平台调试C#程序

下载GetVsDbg.sh &#xff0c;这脚本会下载一个压缩包&#xff0c;然后解压缩&#xff0c;设置x权限等等。但是目标板子连不上&#xff0c;就想办法获取到下载路径&#xff0c;修改这个脚本&#xff0c;显示这个下载链接后&#xff0c;复制一下&#xff0c;用电脑下下来 修改好…

【16】数据结构之基于树的排序算法篇章

目录标题 选择排序简单选择排序树形选择排序 堆排序堆的定义Heap小跟堆大根堆堆的存储堆的代码设计堆排序的代码设计 排序算法综合比较 选择排序 基本思想&#xff1a;从待排序的序列中选出最大值或最小值&#xff0c;交换该元素与待排序序列的头部元素&#xff0c;对剩下的元…

华熙生物亮相消博会,这次又带来了什么样的变化?

首先&#xff0c;从展示层面来看&#xff0c;华熙生物在消博会上构建科技桥梁&#xff0c;展台主视觉展示糖生物学发展历程与自身发展交织历程&#xff0c;这象征着中国生物科技企业从产业突围到定义全球标准的蜕变。这一展示不仅提升了华熙生物的品牌形象&#xff0c;更向外界…

大象机器人推出myCobot 280 RDK X5,携手地瓜机器人共建智能教育机

摘要 大象机器人全新推出轻量级高性能教育机械臂 myCobot 280 RDK X5&#xff0c;该产品集成地瓜机器人 RDK X5 开发者套件&#xff0c;深度整合双方在硬件研发与智能计算领域的技术优势&#xff0c;实现芯片架构、软件算法、硬件结构的全栈自主研发。作为国内教育机器人生态合…

【初阶数据结构】——算法复杂度

一、前言 1、数据结构是什么&#xff1f; 数据结构(Data Structure)是计算机存储、组织数据的⽅式&#xff0c;指相互之间存在⼀种或多种特定关系的数 据元素的集合。没有⼀种单⼀的数据结构对所有⽤途都有⽤&#xff0c;所以我们要学各式各样的数据结构&#xff0c; 如&…

Google-A2A协议全面解析:一文掌握Agent-to-Agent协议的核心与应用

前言&#xff1a; 在当今人工智能技术飞速发展的时代&#xff0c;智能体&#xff08;Agent&#xff09;已悄然融入我们生活的各个角落。无论是个人智能助手&#xff0c;还是企业的自动化工具&#xff0c;各类AI代理的应用愈发广泛。但目前这些智能体之间大多处于孤立状态&…

Linux-服务器添加审计日志功能

#查看audit软件是否在运行(状态为active而且为绿色表示已经在运行) systemctl start auditd #如果没有在运行的话,查看是否被系统禁用 (audit为0表示被禁用) cat /proc/cmdline | grep -w "audit=0" #修改/etc/default/grub里面audit=0 改为audit=1 #更新GRUB…

基于机器视觉的多孔零件边缘缺陷检测(源码C++、opencv、凸包、凸缺陷检测)

&#x1f451;主页&#xff1a;吾名招财 &#x1f453;简介&#xff1a;工科学硕&#xff0c;研究方向机器视觉&#xff0c;爱好较广泛… ​&#x1f4ab;签名&#xff1a;面朝大海&#xff0c;春暖花开&#xff01; 基于机器视觉的多孔零件边缘缺陷检测&#xff08;源码C、ope…

如何使用AI辅助开发CSS3 - 通义灵码功能全解析

一、引言 CSS3 作为最新的 CSS 标准&#xff0c;引入了众多新特性&#xff0c;如弹性布局、网格布局等&#xff0c;极大地丰富了网页样式的设计能力。然而&#xff0c;CSS3 的样式规则繁多&#xff0c;记忆所有规则对于开发者来说几乎是不可能的任务。在实际开发中&#xff0c…

MySQL入门:数据表的创建

​今天我们来介绍一下除HTML外的另一种语言&#xff1a;MySQL语言&#xff1b; MySQL&#xff1a;即一种用于管理和处理关系数据库的标准语言。要用于执行查询、更新、管理数据库中的数据以及定义和操作数据库结构。 接下来我会逐一介绍它的作用以及其中数据表&#xff0c;数据…