【位运算】算法实战

文章目录

  • 一、算法原理
    • 常见的位运算总结
  • 二、算法实战
    • 1. leetcode面试题01.01. 判断字符是否唯一
    • 2. leetcode268 丢失的数字
    • 3. leetcode371 两整数之和
    • 4. leetcode004 只出现一次的数字II
    • 5. leetcode面试题17.19. 消失的两个数字
  • 三、总结


一、算法原理

计算机中的数据都以二进制形式存储和处理,位运算直接对二进制位进行操作。常见的位运算符包括与(&)、或(|)、异或(^)、取反(~)和左移(<<)、右移(>>)等。

在这里插入图片描述


常见的位运算总结

  1. 基础位运算
    在这里插入图片描述
  2. 给一个数n,确定它的二进制表示中第x位是0还是1
    在这里插入图片描述
  3. 将一个数n的二进制表示的第x位修改成1
    在这里插入图片描述
  4. 将一个数n的二进制表示的第x位修改成0
    在这里插入图片描述
  5. 位图的思想
    在这里插入图片描述
  6. 提取一个数(n)二进制表示中最右侧的1
    在这里插入图片描述
  7. 干掉一个数(n)二进制表示中最右侧的1
    在这里插入图片描述
  8. 位运算的优先级: 能加括号就加括号
  9. 异或(^)运算的运算律
    在这里插入图片描述

二、算法实战

1. leetcode面试题01.01. 判断字符是否唯一

在这里插入图片描述
判断字符是否唯一

解题思路:位图的思想

这道题目我们可以使用位图的思想来解决,因为题目告诉我们字符串中只有小写字母,所以我们只需要一个int类型的整数来充当位图的32个bit位即可。

首先,将位图的所有bit位置为零,默认字符串中的字符都未在位图中出现过。然后遍历整个字符串,检测该字符是否在位图中出现过,如果当前字符未在位图中出现过,说明当前字符是第一次出现,此时我们将其在位图中的位置(当前字符-'a')置为1即可,然后接着向后遍历字符串,如果该字符再次出现,我们就可以从位图中检测到该字符已经在出现过了。直接返回false即可,否则继续向后遍历字符串,如果遍历所有字符后发现都只出现一次,则说明该字符串符合题意。

代码实现:

class Solution {
public:
    bool isUnique(string astr) {
        int num = 0;
        
        for(int i = 0; i < astr.size(); i++)
        {
            int index = astr[i] - 'a';
            if(((num>>index) & 1) == 1)
                return false;
            else
                num |= 1 << index;
        }
        return true;
    }
};

2. leetcode268 丢失的数字

在这里插入图片描述
丢失的数字

解题思路:异或运算

因为题目中告诉我们数组中【1~n】丢失了一个数字,所以我们可以先将数组中的数字 ^ 起来,然后在将这个 ^ 的结果与【1~n】中所有的数字异或,因为按位 ^ 运算满足交换律和结合律,所以按位 ^ 的结果中,丢失的数字出现了一次,其余的数字都出现了两次,将这一堆数字异或起来,结果即为丢失的数字。

在这里插入图片描述

代码实现:

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

3. leetcode371 两整数之和

在这里插入图片描述
两整数之和

解题思路:异或运算-无进位相加

因为题目要求我们不能使用运算符+-来计算两整数之和,因此我们可以将整数 a 和 b 的和,拆分为 a 和 b 的无进位相加结果进位结果的和无进位相加结果 我们可以使用两整数^来实现,进位结果我们可以使用(a & b) << 1来实现。下面我们来举一个例子:

在这里插入图片描述

每次将无进位相加结果进位结果的和分别赋予a和b,循环此过程,直到进位为 0。最终a就是我们所要求的结果。当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模的余数。因此,我们可以使用无符号类型来防止溢出。

代码实现:

lass Solution {
public:
    int getSum(int a, int b) {
        while(b != 0)
        {
            int x = a ^ b; // 先算出无进位相加的结果
            unsigned int carry = (a & b) << 1; // 算出进位
            a = x;
            b = carry;
        }
        return a;
    }
};

4. leetcode004 只出现一次的数字II


只出现一次的数字II

解题思路:

数组中的每个元素的每一个二进制位不是1就是0,而题目中又告诉我们只有一个元素出现一次,其余元素都出现了三次,所以对于数组中的每一个元素 x,我们使用位运算 (x >> i) & 1 得到 x 的第 i 个二进制位,并将它们相加再对 3 取余,得到的结果一定为 0 或 1,即为答案的第 i 个二进制位。

所以,答案的第 i 个二进制位就是数组中所有元素的第 i 个二进制位之和除以 3 的余数。可以先初始化一个ret = 0,然后根据余数的值来判断该数对应的二进制位应该置为0还是1,如果余数为1,我们则需要手动将该位置置为1,ret |= (1 << i),否则则不需要处理。

代码实现:

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

5. leetcode面试题17.19. 消失的两个数字

在这里插入图片描述
消失的两个数字

解题思路:

这道题目其实我们可以用力扣的第260题 只出现一次的数字III 的思想来做,具体解决方式如下:

因为数组中包含从 1 到 N 所有的整数,但其中缺了两个数字,现在数组的长度为n。所以数组中原本应该包含的数字是【1,n + 2】。我们可以将原来数组中的数字和【1,n + 2】,组合到一起,现在我们就可以将问题转化一下:求数组中只出现一次的两个数字。

解决这个问题我们可以分为两步:整体异或分组异或。整体异或:将题目给出的数组中的所有数字和【1,n + 2】中所包含的数字全部异或起来,得到的结果就是只出现一次的两个数字的异或结果:a^b。接下来我们需要提取出该数字二进制表示中最低位的1。假设该位置为第k位,我们就可以把 所有数中的元素(题目中给出的数字和【1,n + 2】的数字)分成两类,其中一类包含所有二进制表示的第 k 位为 0 的数,另一类包含所有二进制表示的第 k 位为 1 的数。

  • 对于任意一个在 所有元素中 出现两次的元素,该元素的两次出现会被包含在同一类中;
  • 对于任意一个在所有元素中只出现了一次的元素,即 x1 和 x2, 他们会被包含在不同的类中。

因此,我们将这两类元素分别异或起来,就可以得到不同的两个结果,一个结果是x1,另一个结果是x2,这两个数字则是只出现一次的两个数字,即本题中我们需要寻找的两个消失的数字。

代码实现:

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        int ret = 0;
        for(int i = 1; i <= nums.size()+2; i++)
            ret ^= i;
        for(auto e : nums) ret ^= e;
        int lowbit = ret & -ret; // 找出最后一个不同的比特位
        int ret1 = 0, ret2 = 0;
        for(int i = 1; i <= nums.size()+2; i++){ // 分组异或
            if(lowbit & i) ret1 ^= i;
            else ret2 ^= i;
        }
        for(auto e : nums){
            if(lowbit & e) ret1 ^= e;
            else ret2 ^= e;
        }
        return {ret1, ret2};
    }
};

三、总结

位运算可以直接操控数字的二进制位,节约内存,使程序运行更快,可靠性高。在算法中使用位运算可以大大降低算法的时间复杂度和空间复杂度,恰当的位运算使用也能使程序变得更加简洁和优美。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

243:vue+Openlayers 更改鼠标滚轮缩放地图大小,每次缩放小一点

第243个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayers项目中设置鼠标滚轮缩放地图大小,每次滑动一格滚轮,设定的值非默认值1。具体的设置方法,参考源代码。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源…

SMC_TRAFO_GantryCutter2 (FB) 带刀片旋向龙门

裁布机&#xff1a;刀片按XY走向&#xff0c;偏转刀片角度。 pi&#xff1a;目标位置矢量&#xff08;x&#xff0c;y&#xff09;&#xff0c;插值器的输出 v&#xff1a;当前路径切线的矢量&#xff0c;插值器的输出 dOffsetX&#xff1a; x轴的附加偏移 dOffsetY&#xf…

【C++精华铺】9.STL string

目录 1. string类的优势 2. string类的常用接口 2.1 常用构造 1. 空串构造&#xff1a;string(); 2. C串构造&#xff1a;string(const char* s); 3. 拷贝构造&#xff1a;string(const string& str); 4. 字符填充构造&#xff1a;string(size_t n, char c); 5. 迭代…

大数据开发要学习什么?学完又能做什么

学习大数据需要掌握什么语言基础&#xff1f; 1、Java基础 大数据框架90%以上都是使用Java开发语言&#xff0c;所以如果要学习大数据技术&#xff0c;首先要掌握Java基础语法以及JavaEE方向的相关知识。 2、MySQL数据库 这是学习大数据必须掌握的知识之一。数据的操作语言是…

研磨设计模式day11观察者模式

目录 场景 代码示例 定义 观察者模式的优缺点 本质 何时选用 简单变型-区别对待观察者 场景 我是一家报社&#xff0c;每当我发布一个新的报纸时&#xff0c;所有订阅我家报社的读者都可以接收到 代码示例 报纸对象 package day11观察者模式;import java.util.Observ…

Ubuntu20.04配置mysql配置主从复制

ubuntu20.04&#xff1a;mysql主库 sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf # 修改完毕重启 sudo service mysql stop sudo service mysql start主库mysqld.cnf配置 [mysqld] ... # bind-address>->--- 127.0.0.1 # 注释掉&#xff0c;允许外部连接 # mysqlx-b…

Spark整合hive的时候出错

Spark整合hive的时候 连接Hdfs不从我hive所在的机器上找&#xff0c;而是去连接我的集群里的另外两台机器 但是我的集群没有开 所以下面就一直在retry 猜测&#xff1a; 出现这个错误的原因可能与core-site.xml和hdfs-site.xml有关&#xff0c;因为这里面配置了集群的nameno…

浅析 GlusterFS 与 JuiceFS 的架构异同

在进行分布式文件存储解决方案的选型时&#xff0c;GlusterFS 无疑是一个不可忽视的考虑对象。作为一款开源的软件定义分布式存储解决方案&#xff0c;GlusterFS 能够在单个集群中支持高达 PiB 级别的数据存储。自从首次发布以来&#xff0c;已经有超过十年的发展历程。目前&am…

Pycharm通过SSH配置centos上Spark环境

直接在shell进行pyspark进行编程&#xff0c;程序没有办法写得太长&#xff0c;而且我们希望能够实现一个及时给出结果的编程环境&#xff0c;可以使用pycharm连接centos上的spark&#xff0c;进行本地编程&#xff0c;同步到centos系统中运行程序&#xff0c;并把结果返回pych…

IMS中Binder案例

IMS中Binder案例 1、FWK层中AIDL形式1.1 服务端实现Stub1.2 客户端获取proxy 2、Native层中AIDL形式2.1 服务端对应Bn端2.2 客户端对应Bp端 android12-release 1、FWK层中AIDL形式 Android 接口定义语言 (AIDL)、Android 应用层 到 HAL 层 AIDL形式是Android中binder机制的具体…

HAproxy服务及keepalived+haproxy高可用

本节主要学习AHproxy 的概述&#xff0c;安装&#xff0c;调度算法&#xff0c;配置文件&#xff0c;负载均衡&#xff0c;配置syslog日志&#xff0c;keepalivedhaproxy实现高可用。 目录 一、概述 1、简介 2、核心功能 3、关键特性 4、应用场景 二、安装 1.内核配置 …

Delphi 开发手持机(android)打印机通用开发流程(举一反三)

目录 一、场景说明 二、厂家应提供的SDK文件 三、操作步骤&#xff1a; 1. 导出Delphi需要且能使用的接口文件&#xff1a; 2. 创建FMX Delphi项目&#xff0c;将上一步生成的接口文件&#xff08;V510.Interfaces.pas&#xff09;引入: 3. 将jarsdk.jar 包加入到 libs中…

开始MySQL之路——MySQL安装和卸载

MySQL的介绍 MySQL数据库管理系统由瑞典的DataKonsultAB公司研发&#xff0c;该公司被Sun公司收购&#xff0c;现在Sun公司又被Oracle公司收购&#xff0c;因此MySQL目前属于Oracle旗下产品。 MySQL所使用的SQL语言是用于访问数据库的最常用标准化语言。MySQL软件采用了双授权…

四、Kafka Broker

4.1.1 Zookeeper 存储的 Kafka 信息 4.1.2 Kafka Broker 总体工作流程 4.2 生产经验 - 节点的服役和退役 自己的理解&#xff1a;其实就是将kafka的分区&#xff0c;负载到集群中的各个节点上。 1、服役新节点 2、退役旧节点 4.3 kafka副本 1、副本的作用 2、Leader的…

共享内存 windows和linux

服务端&#xff0c;即写入端 #include <iostream> #include <string.h> #define BUF_SIZE 1024 #ifdef _WIN32 #include <windows.h> #define SHARENAME L"shareMemory" HANDLE g_MapFIle; LPVOID g_baseBuffer; #else #define SHARENAME "sh…

Node.js 的 Buffer 是什么?一站式了解指南

在 Node.js 中&#xff0c;Buffer 是一种用于处理二进制数据的机制。它允许你在不经过 JavaScript 垃圾回收机制的情况下直接操作原始内存&#xff0c;从而更高效地处理数据&#xff0c;特别是在处理网络流、文件系统操作和其他与 I/O 相关的任务时。Buffer 是一个全局对象&…

Sql Server导出数据库到另一个数据库

1.打开sql server数据库&#xff0c;连接到服务器后&#xff0c;找到需要导出的数据库&#xff0c;右击后选择 任务->导出数据。 2.点击 下一步。 3.身份验证可以使用SQL Server身份验证&#xff0c;就是当时建立连接时的用户名和密码&#xff0c;数据库名称使用默认的&…

深度学习入门教学——二分分类

1、什么是二分分类&#xff1f; 二分分类就是判断“有”和“没有”、“是”和“不是”的问题&#xff0c;也就是监督学习中的分类问题。例如&#xff0c;输入一张图片&#xff0c;输出识别该图片的标签。计算机输入图片转化过程如下&#xff1a; 2、神经网络常用符号表示 (x, …

一次harbor升级导致镜像项目访问无权限问题

一、问题背景 将环境中现运行的harbor版本升级到2.6.2版本&#xff0c;相关同事升级完&#xff0c;发现有部分镜像项目点进去报无权限问题&#xff0c;镜像项目无法使用&#xff0c;但是也有部分项目是可以正常提供使用的。 二、问题处理过程 1、根据报错反馈没权限&#xff…

量化QAT QLoRA GPTQ

模型量化的思路可以分为PTQ&#xff08;Post-Training Quantization&#xff0c;训练后量化&#xff09;和QAT&#xff08;Quantization Aware Training&#xff0c;在量化过程中进行梯度反传更新权重&#xff0c;例如QLoRA&#xff09;&#xff0c;GPTQ是一种PTQ的思路。 QAT…