优选算法之位运算

news2024/11/28 2:33:48

目录

一、常见位运算总结

1.基础位运算

2.给定一个数 n,确定它的二进制表示中的第 x 位是 0 还是 1

3.将一个数 n 的二进制表示的第 x 位修改成1

4.将一个数 n 的二进制表示的第 x 位修改成 0

5.提取一个数 n 二进制表示中最右侧的1

6.干掉一个数 n 二进制表示中最右侧的 1

7.位运算的优先级

8.异或(^)运算的运算律

二、判断字符是否唯一

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

2.题目描述:

3.解法(位图的思想)

🌴算法思路:

🌴算法代码:

三、丢失的数字

1.题目链接:268. 丢失的数字

2.题目描述:

3.解法(位运算)

🌴算法思路:

🌴算法代码:

四、 两整数之和

1.题目链接:371. 两整数之和

2.题目描述:

3.解法(位运算)

🌴算法思路:

🌴算法代码:

五、只出现一次的数字II

1.题目链接:137. 只出现一次的数字 II

2.题目描述:

3.解法(比特位计数)

🌴算法思路:

🌴算法代码:

六、消失的两个数字

1.题目链接:面试题 17.19. 消失的两个数字

2.题目描述:

3.解法(位运算)

🌴算法思路:

🌴算法代码:

七、位1的个数

1.题目链接:191. 位1的个数

2.题目描述:

3.解法(位运算)

🌴算法思路:

🌴算法代码:


一、常见位运算总结

1.基础位运算

位运算是直接对整数在内存中的二进制表示进行操作的运算。这些运算通常非常高效,因为它们是在硬件级别执行的。以下是几种基本的位运算符及其用法:

1. 按位与(`&`)

  • 当两个相应的二进制位都是1时,结果为1;否则为0。
  • 记忆:有 0 就是 0(看这个符号中间是不是有两个 0)
  • 例如,`5 & 3` 的结果是 `1`,因为 `5` 在二进制中是 `101`,而 `3` 是 `011`。

2. 按位或(`|`)

  • 当两个相应的二进制位中至少有一个是1时,结果为1;否则为0。
  • 记忆:有 1 就是 1(看这个符号像不像数字 1)
  • 例如,`5 | 3` 的结果是 `7`,因为 `5` 在二进制中是 `101`,而 `3` 是 `011`。

3. 按位异或(`^`)

  • 当两个相应的二进制位不同时,结果为1;相同时为0。
  • 记忆:(1)相同为0,相异为1; 
  • (2)无进位相加。
  • 例如,`5 ^ 3` 的结果是 `6`,因为 `5` 在二进制中是 `101`,而 `3` 是 `011`。

4. 按位取反(`~`)

  • 将每个二进制位反转,1变成0,0变成1。
  • 例如,`~5` 的结果取决于你的系统是使用补码表示负数还是符号加绝对值表示法。在大多数现代计算机上,它将返回 `-6`。

5. 左移(`<<`)

  • 将一个二进制位模式向左移动指定的位数。
  • 例如,`5 << 1` 的结果是 `10`,因为 `5` 在二进制中是 `101`,左移一位后变成 `1010`。

6. 右移(`>>`)

  • 将一个二进制位模式向右移动指定的位数。
  • 例如,`5 >> 1` 的结果是 `2`,因为 `5` 在二进制中是 `101`,右移一位后变成 `10`。

2.给定一个数 n,确定它的二进制表示中的第 x 位是 0 还是 1

3.将一个数 n 的二进制表示的第 x 位修改成1

4.将一个数 n 的二进制表示的第 x 位修改成 0

5.提取一个数 n 二进制表示中最右侧的1

6.干掉一个数 n 二进制表示中最右侧的 1

7.位运算的优先级

从高到底依次为:

  • 按位取反 (~) > 位移运算符 (<<>>) > 按位与 (&) > 按位异或 (^) 按位或 (|)
  • 如果记不住那就只需要记住能加括号就加括号

注意:这些运算符的优先级通常低于算术运算符(如 加法和 乘法*),但高于赋值运算符(如=, +=, &=等)。

8.异或(^)运算的运算律

二、判断字符是否唯一

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

2.题目描述:

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例 1:

输入: s = "leetcode"
输出: false 

示例 2:

输入: s = "abc"
输出: true

限制:

  • 0 <= len(s) <= 100
  • s[i]仅包含小写字母
  • 如果你不使用额外的数据结构,会很加分。

3.解法(位图的思想

🌴算法思路:

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

那么我们就可以用⼀个「整数」来充当「哈希表」。

🌴算法代码:

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

三、丢失的数字

1.题目链接:268. 丢失的数字

2.题目描述:

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

示例 1:

输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 2:

输入:nums = [0,1]
输出:2
解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 3:

输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。

示例 4:

输入:nums = [0]
输出:1
解释:n = 1,因为有 1 个数字,所以所有的数字都在范围 [0,1] 内。1 是丢失的数字,因为它没有出现在 nums 中。

3.解法(位运算

🌴算法思路:

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

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

🌴算法代码:

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

四、 两整数之和

1.题目链接:371. 两整数之和

2.题目描述:

给你两个整数 a 和 b ,不使用 运算符 + 和 - ,计算并返回两整数之和。

示例 1:

输入:a = 1, b = 2
输出:3

示例 2:

输入:a = 2, b = 3
输出:5

3.解法(位运算

🌴算法思路:

  1. 异或 ^ 运算本质是「无进位加法」;
  2. 按位与 & 操作能够得到「进位」;
  3. 然后⼀直循环进行,直到「进位」变成 0 为止。

🌴算法代码:

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

五、只出现一次的数字II

1.题目链接:137. 只出现一次的数字 II

2.题目描述:

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

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

示例 1:

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

示例 2:

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

3.解法(比特位计数

🌴算法思路:

设要找的数为 ret 。

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

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

🌴算法代码:

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

六、消失的两个数字

1.题目链接:面试题 17.19. 消失的两个数字

2.题目描述:

给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?

以任意顺序返回这两个数字均可。

示例 1:

输入: [1]
输出: [2,3]

示例 2:

输入: [2,3]
输出: [1,4]

3.解法(位运算

🌴算法思路:

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

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

🌴算法代码:

class Solution 
{
public:
    vector<int> missingTwo(vector<int>& nums) 
    {
        // 1. 将所有的数异或在⼀起
        int tmp = 0;
        for (auto x : nums)
            tmp ^= x;

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

七、位1的个数

1.题目链接:191. 位1的个数

2.题目描述:

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

示例 1:

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

示例 2:

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

示例 3:

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

3.解法(位运算

🌴算法思路:

观察这个运算:n & (n−1),其运算结果恰为把 n 的二进制位中的最低位的 1 变为 0 之后的结果。

这样我们可以利用这个位运算的性质加速我们的检查过程,在实际代码中,我们不断让当前的 n 与 n−1 做与运算,直到 n 变为 0 即可。因为每次运算会使得 n 的最低位的 1 被干掉,因此运算次数就等于 n 的二进制位中 1 的个数。

🌴算法代码:

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

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

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

相关文章

分布式存储系统架构及应用

分布式存储系统概述&#xff08;详细、全面&#xff09; 【摘要】深度剖析分布式存储系统的可靠性、可用性、IO性能、数据存储效率、安全性及管理性&#xff0c;为寻求了解此领域的读者提供实用参考。 一、 内容总括 分布式存储系统&#xff0c;依托网络互联的多节点软硬件协同…

人脸识别又进化:扫一下 我就知道你得了啥病

未来&#xff0c;扫下你的脸&#xff0c;可能就知道你得啥病了。没在瞎掰&#xff0c;最近的一项研究成果&#xff0c;还真让咱看到了一点眉目。北大的一个研究团队&#xff0c;搞出来一个 AI &#xff0c;说是用热成像仪扫一下脸&#xff0c;就能检测出有没有高血压、糖尿病和…

工作纪实54-git使用ssh方式

很多居家的小伙伴要重新clone项目&#xff0c;但是忘记了密码&#xff0c;最恶心的是idea还会自动帮你记录密码&#xff0c;如果输错了&#xff0c;会很恶心&#xff0c;使用ssh则不会&#xff1b;还有一个好处就是&#xff0c;集团的密码一般都是几个月更新一次&#xff0c;ss…

基于Frp搭建Window-Linux内网穿透完整流程

什么是内网穿透? 内网穿透是我们在进行网络连接时的一种术语&#xff0c;也叫做NAT穿透&#xff0c;即在计算机是局域网内的时候&#xff0c;外网与内网的计算机的节点进行连接时所需要的连接通信&#xff0c;有时候就会出现内网穿透不支的情况。内网穿透的功能就是&#xff0…

只出现一次的数字-位运算

题目描述&#xff1a; 个人题解&#xff1a; 代码实现&#xff1a; class Solution { public:int singleNumber(vector<int>& nums) {int ret 0;for (auto e: nums) ret ^ e;return ret;} };复杂度分析&#xff1a; 时间复杂度&#xff1a;O(n)&#xff0c;其中 n…

19018 正则序列

这个问题可以通过排序和计数来解决。首先&#xff0c;我们将数组排序&#xff0c;然后我们遍历排序后的数组&#xff0c;对于每个元素&#xff0c;我们将它变为它应该在正则序列中的值&#xff0c;也就是它的索引加1。我们将这个变化的绝对值累加起来&#xff0c;这就是我们需要…

STM32智能农业灌溉系统教程

目录 引言环境准备智能农业灌溉系统基础代码实现&#xff1a;实现智能农业灌溉系统 4.1 数据采集模块 4.2 数据处理与分析模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;农业监测与优化问题解决方案与优化收尾与总结 1. 引言 智能农业灌溉系统通…

Sklearn实例:水果多分类

机器学习五步&#xff1a; 加载数据集分割数据集建立模型训练模型预测模型 导入库文件 import numpy as np #科学计算库 import matplotlib.pyplot as plt #绘图库可视化函数 import pandas as pd #数据处理库&#xff0c;数据分析库 import seaborn as sns #高级数据可视化…

AI技术修复奥运珍贵历史影像,《永不失色的她》再现百年奥运女性光彩

Greatness of HER &#xff01; AI致敬 , 了不起的「她」。 7月25日&#xff0c;在国际奥委会和各方力量的支持下&#xff0c;阿里云以AI技术修复奥运珍贵历史影像&#xff0c;让百年奥运女性的伟大光彩被看见&#xff0c;并在巴黎推出《永不失色的她》全球首映礼。 国际奥委会…

【练习】使用DevEco Studio编写鸿蒙代码,实现卡片效果,主要是练习布局

效果展示 实现代码 build() {Column(){Column(){Image($r("app.media.avatar")).width("100%").borderRadius({topLeft:10,topRight:10})Text("今晚吃这个 | 每日艺术分享 No.43").fontSize(14).fontWeight(600).lineHeight(22).height(60)Row(…

Xlua原理分析 四

前面已经介绍了Xlua的通信原理&#xff0c;这篇主要记录Xlua如何做到Hotfix的。 我们项目就用到Xlua的Hotfix特性&#xff0c;周更用Lua去修改代码。版本内用C#开发。这点我觉得是Xlua比toLua强大的重要特性之一。 如何使用Hotfix本篇不介绍了&#xff0c;看Xlua教程懂得都懂…

网页上空格

&#xA0; no-break space(普通的英文半角空格但不换行) 中文全角空格 (一个中文宽度) &ensp; en空格(半个中文宽度) &emsp; em空格 (一个中文宽度) 四分之一em空格 (四分之一中文宽度) 相比平时的空格()&#xff0c;&nbsp拥有不间断(non-breaking)特性。即连续…

postgresql 您要的日期查询都在这

1、获取当前日期 select now();select current_timestamp;返回值均是当前年月日、时分秒&#xff0c;且秒保留6位小数&#xff0c;两种方式等价 select current_time;返回值&#xff1a;时分秒&#xff0c;秒最高精确到6位 select current_date;返回值&#xff1a;年月日 2…

HarmonyOS 鸿蒙DFX能力简介

DFX简介&#xff1a; Development and Feedback eXchange&#xff08;‌DFX&#xff09;‌&#xff0c;‌用于开发、‌测试和维护鸿蒙应用&#xff0c;提供一系列的工具和功能&#xff0c;‌帮助开发者在开发过程中进行性能分析、‌故障检测、‌异常处理。比如异常处理、性能分…

【qt小系统】传感器云平台3D散点图(附源码)

摘要&#xff1a;本文主要使用QT5&#xff0c;实现了一个传感器云平台的小示例&#xff0c;模拟的是各类传感器的添加&#xff0c;例如&#xff1a;热成像传感器、温度传感器、超声波传感器&#xff0c;模拟添加完成后&#xff0c;会自动将此传感器的三维坐标增加到3D散点图上&…

【每日一篇】UrbanGPT:时空大语言模型 【方便自己看】

摘要 时空预测旨在预测和洞察城市环境在时间和空间上不断变化的动态。它的目的是预测未来的模式&#xff0c;趋势和城市生活的各个方面的事件&#xff0c;包括交通&#xff0c;人口流动和犯罪率。虽然已经有许多努力致力于开发神经网络技术来准确预测时空数据&#xff0c;但重…

【C 语言】深入理解冒泡排序算法

0. 前言 冒泡排序是一种经典且基础的排序算法。它虽然在效率上并非最优&#xff0c;但对于初学者理解排序的基本概念和逻辑有着重要的意义。 1. 冒泡排序的基本思想 冒泡排序的基本思想是通过反复比较相邻的元素并交换它们&#xff08;如果顺序错误&#xff09;&#xff0c;…

基于GEC6818开发板+Linux+Qt设计的智能养老院出入管理系统(195)

一、前言 1.1 项目介绍 【1】项目功能介绍 随着我国老龄化进程的加快,养老问题日益突出,如何有效保障老年人的生活质量与安全成为社会关注的重点。智能化、信息化技术的发展为解决这一问题提供了新的思路和手段。基于Linux系统的智能养老院出入管理系统应运而生,为了实现…

记录一次使用Docker部署skywalking的过程

临时一个测试系统需要追一下bug&#xff0c;所以计划单节点部署一套skywalking进行调用链分析。 网上扒拉了几篇&#xff0c;都有点问题&#xff0c;这里单独记录一个。 首先skywalking需要是用es做数据源&#xff0c;当然也有mysql等多个版本&#xff0c;这里用的es。 同时…