Leetcode算法热题 --- 数组篇丢失的数字

Posted 大家好我叫张同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode算法热题 --- 数组篇丢失的数字相关的知识,希望对你有一定的参考价值。


题目内容:

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

(进阶: 你能否实现线性时间复杂度、仅使用额外常数空间的算法解决此问题?)


Leetcode题目链接(点击即可跳转):丢失的数字


题目理解:

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

假设 n = 3,也就是说这个数组原本应该有的元素为[0,3],也就是{0,1,2,3}四个元素;
假设n=1,那么数组中的元素应该为{0,1}两个元素。
现在因为某种神秘的原因,导致原本数组中的某个元素丢失了,比如说n=3的时候,2丢失了,那么数组剩下的元素仅有{0,1,3},现在就是要求我们找出这个丢失的数字。


解题思路

思路一:求和做差法

假设n=5,那么数组中的元素应该为{0,1,2,3,4,5}(实际在数组中存放的元素顺序可以为任意的)

若数组中某一个元素丢失了,假设3不见了。

若要求丢失的数字3,

1)我们可以先让原数组(没丢之前)中的内容累加得到和s1(如果数组元素个数为n,那么原数组的内容必然为[0,n],理解这一点很重要)
2)然后让(丢失数字后的)新数组累加得到和s2
3)两者相减 s1 - s2 即可得到丢失的数字

代码实现:

int missingNumber(int* nums, int numsSize){
    //numsSize代表元素个数,也就是n
    //1)先求出0-n之间的累加值
    int s1 = 0;
    int i = 0;
    for(i = 0; i <= numsSize; i++)//注意这里需要取 “=”
    {
        s1 += i;
    }
    //2)求出数组nums中的累加值
    int s2 = 0;
    for(i = 0; i < numsSize; i++)//这里不能取等号,n个元素,下标最大为n-1,下标从0开始的
    {
        s2 += nums[i];
    }
    //3)求丢失的数字
    int miss_number = s1 - s2;
    return miss_number;
}


思路二:异或找单法

要理解这个方法,我们要先知道有关异或操作符 “^” 的一些基本知识

^ 指的对应二进制位置相同为0,相应为1,什么意思呢?

为了方便理解,我用8位的二进制3和5进行举例:

如果将3和5异或^运算的结果6,再去跟3异或会怎么样呢?

会得到5,也就是一开始参与异或运算的数字。
那如果将6和5进行异或会怎么样呢?

会得到原来参与运算的数字3!

也就是说

3 ^ 5 ^ 3 = 5
3 ^ 5 ^ 5 = 3

有没有找到什么规律?是不是相同的数字进行异或就消失了,类似于我们看科幻电影里面经常会出现的物质和反物质碰撞就湮灭了。
更进一步,实际上这个规律跟数字出现的先后顺序无关,也就是说

3 ^ 3 ^ 5
= 3 ^ 5 ^ 3
= 5 ^ 3 ^ 3
= 5

接下来我们就可以利用这个方法来找出丢失的数字。具体的思路是:

1)让[0,n]所有的数字进行异或得到Xor1
2)让数组中所有元素进行异或得到Xor2
3)让Xor1和Xor2进行异或,就能找出丢失的数字(因为丢失的数字只出现一次,其他数字均出现两次,经过一系列异或运算后会被湮灭,仅剩下出现一次的那个数字,也就是丢失的数字,这个数字有时候也会被人称为单身狗)

代码实现:

int missingNumber(int* nums, int numsSize){
    int Xor1 = 0;
    int i = 0;
    //1)将0-n之间的所有数字进行异或,得到结果Xor1
    for(i = 1; i <= numsSize; i++)
    {
        Xor1 ^= i;
    }
    //2)将数组中所有元素进行异或,得到结果Xor2
    int Xor2 = nums[0];
    for(i = 1; i < numsSize; i++)
    {
        Xor2 ^= nums[i];
    }
    //3)将Xor1和Xor2进行异或得到丢失的数字
    int miss_number = Xor1 ^ Xor2;
    return miss_number;
}


另外还有其他的方法,这里简要提一下

思路三:排序法

将数组中所有的元素按找升序排序,那么下标为0的元素就应该是数字0,下标为1的元素就应该是数字1,下标为m的元素就应该是数字m(m < n)


思路四:哈希表法

利用哈希表,我们可以直接查询每个数是否在数组中出现过来找出缺失的数字。

以上是关于Leetcode算法热题 --- 数组篇丢失的数字的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点# LeetCode 热题 HOT 100:在排序数组中查找元素的第一个和最后一个位置

#yyds干货盘点# LeetCode 热题 HOT 100:全排列

数学与数字6:LeetCode268. 丢失的数字

悄悄学算法,然后惊艳所有人:零基础学算法 LeetCode 热题 HOT 100

数学与数字6:LeetCode268. 丢失的数字

#yyds干货盘点# LeetCode 热题 HOT 100:最大子数组和