【算法专题突破】--- 位运算 --- 丢失的数字(难度⭐) && 只出现一次的数字 III (难度⭐⭐)&& 消失的两个数字(难度⭐⭐⭐)(2)

一,丢失的数字

1. 题目解析

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

这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。

2.算法原理

首先,我们设定一个长度为n的数组。理想情况下,如果这个数组是从0到n-1的连续整数序列,那么它应该包含所有从0到n-1的整数。但是,由于某种原因,数组中缺失了一个数字,因此它现在是一个不完整的序列。

我们的目标是找出这个缺失的数字。为了实现这一目标,我们可以利用异或运算的一个关键特性,即任何数和0进行异或运算,结果仍然是原来的数;而任何数和其自身进行异或运算,结果则为0。这一特性使得异或运算在解决这类问题时非常有用。

我们可以按照以下步骤来寻找缺失的数字:

  1. 初始化异或结果:首先,我们设置一个变量来保存异或运算的结果,初始值为0。这个变量将用于存储所有应该出现在数组中的数字(即从0到n-1的所有整数)的异或结果。
  2. 计算应该存在的数字的异或:接下来,我们遍历从0到n-1的所有整数,并将它们依次与异或结果变量进行异或运算。这样,我们就得到了一个包含了所有应该存在于数组中的数字的异或结果。
  3. 计算实际数组中数字的异或:然后,我们遍历数组中的每一个数字,并将它们也依次与异或结果变量进行异或运算。由于数组中的数字与前面计算出的应该存在的数字的集合相比,只有一个数字是缺失的,因此这一步操作实际上是将这个缺失的数字从异或结果中"消除"了。
  4. 得出缺失的数字:最后,由于异或运算的"消消乐"特性,最终保存在异或结果变量中的数字,就是那个在数组中缺失的数字。

通过以上步骤,我们可以有效地找出数组中缺失的那个数字,而无需显式地检查每一个可能的数字是否存在于数组中。这种算法的时间复杂度是O(n),其中n是数组的长度,因此它对于处理大规模数据集也是相当高效的。

3.代码编写

复制代码
class Solution 
{
public:
    int missingNumber(vector<int>& nums) 
    {
        int size = nums.size(), ret = size;
        for(int i = 0; i < size; i++) ret ^= i ^ nums[i];
        //for(const auto &x : nums) ret ^= x;
        return ret;
    }
};

二,只出现一次的数字III

1. 题目解析

题目链接:260. 只出现一次的数字 III

这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。

2.算法原理

一种计算lowbit的方式,就是保留数字的二进制表示中最低位的1,其余位均置为0。举例来说:

  • 设 s 的二进制为 101100,首先我们对 s 进行按位取反得到 ~s,结果为 010011。
  • 接着,我们将 ~s 加 1,根据补码的定义,这实际上相当于计算了 -s,结果是 010100。
  • 此时,我们可以观察到 -s 的效果是将 s 中最低位的1左侧的所有位取反,而最低位1右侧的位保持不变。
  • 最后,我们将 s 与 -s 进行按位与运算,得到 s & -s 的结果为 000100。这样,我们就成功地保留了 s 的最低位的1,而将其余位都置为了0。

3.代码编写

复制代码
class Solution 
{
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
        size_t tmp = 0;
        for(auto x : nums) tmp ^= x;
        int lowbit = tmp & -tmp;
        vector<int> ret(2);
        for(auto x : nums) ret[(x & lowbit) == 0] ^= x;
        return ret;
    }
};

三,消失的两个数字

1. 题目解析

这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。

2.算法原理

本题就是 一,丢失的数字 + 二,260. 只出现⼀次的数字 III 结合 起来的题。

我们将数组中的每个数与区间1, n + 2内的所有数依次进行异或操作。

通过这一步,问题便转化为:有两个数各出现了一次,而其余所有数均出现了两次。这就类似于我们熟知的"只出现一次的数字 III"这道题目。

3.代码编写

复制代码
class Solution 
{
public:
    vector<int> missingTwo(vector<int>& nums) 
    {
        //丢失的数字
        size_t tmp = 0, n = nums.size();
        for(auto x : nums) tmp ^= x;
        for(int i = 1; i <= n + 2; i++) tmp ^= i;
        //只出现一次的数字III
        int lowbit = tmp & -tmp;
        vector<int> ret(2);
        for(auto x : nums) ret[(x & lowbit) == 0] ^= x;
        for(int i = 1; i <= n + 2; i++) ret[(i & lowbit) == 0] ^= i;
        return ret;
    }
};

The Last

嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。

觉得有点收获的话,不妨给我点个赞吧!

如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~

相关推荐
夜之眷属12 分钟前
PriorityQueue:for-each 遍历和 poll 取出,顺序一样吗?
java·服务器·数据结构·后端·算法
‎ദ്ദിᵔ.˛.ᵔ₎34 分钟前
c++11:fuction包装器
开发语言·c++
地平线开发者1 小时前
不是线程越多越快:用 hrt_model_exec 在 征程6M 上给 YOLOv5x 建立性能基线
算法
霍霍的袁1 小时前
【C++】哈希表实现指南:从原理到开放定址法、链地址法的实现
c++·学习·哈希算法·散列表·visual studio
姜鱼问生1 小时前
fail2ban 实战:从默认配置到生产可用
后端·算法·架构
垆边人似月.2 小时前
华为题:全排列
算法·深度优先·图论
杜 硕2 小时前
快速排序详解01
数据结构·算法·排序算法
Matlab程序猿2 小时前
【MATLAB源码-第459期】基于matlab的D-H模型与阻尼最小二乘逆运动学的六自由度机械臂五次轨迹规划及动力学前馈PD控制仿真。
人工智能·算法·matlab·d-h建模·六自由度串联机械臂
信奥卷王2 小时前
[GESP202606 六级] 满二叉树
数据结构·算法
积流成海2 小时前
用代码实现哈希计算器:Web Crypto API 实战
前端·算法·哈希算法·哈希函数·盘子工具站