【LeetCode】数组nums包含从0到n的所有整数,但其中缺了一个,请找出那个缺失的整数(面试题 17.04. 消失的数字)| 数组

1、题目描述:

image-20210728232634257

LeetCode链接:消失的数字

2、解题方法:

对于此道题,我们有哪些解题思路呢?先不管其事件复杂度是否符合题目的要求,我们先分析思路。


解法1:

先将数组中的数由小到大排序,再遍历排序后的结果,如果遍历下标和该下标对应的元素不相等,则返回该下标,如果遍历结束仍然没有符合条件,说明是最后一个数字 n 缺失了,则返回数组长度 numsSize

如果用 qsort 快速排序,时间复杂度是O(N*logN),再加之还要遍历,早已大于了O(N),不符合要求。

下面代码仅作为此解法思路的展示:

int missingNumber(int* nums, int numsSize) 
{
    //因为缺失了一个,数组nums中只有n个元素,数组元素个数numsSize = n
    
    //1. 将数组中的数由小到大排序
    int i = 0;
    int j = 0;
    int temp = 0;
    for (i = 0; i < numsSize - 1; i++)  //BubbleSort共进行n-1趟
    {
        for (j = 0; j < numsSize - 1 - i; j++)  //每一趟比较n-1-i次
        {
            if (nums[j] > nums[j + 1])
            {
                temp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = temp;
            }
        }
    }
    
    //2. 遍历下标和该下标对应的元素
    //如果相等,则继续,不相等,输出缺失的数
    for (i = 0; i < numsSize; i++)
    {
        if (i != nums[i])
            return i;
    }
    return numsSize;
}

解法2:

求出前 n+1 个数字之和,在减去数组中的所有数字,就是缺失的数字。

  1. 求和,计算 0 + 1 + 2 + 3 + 4 + …… + n-1 + n 的值(可用等差数列求和公式)
  2. 减去数组中值的累加,得到的值就是缺失的数字。

该算法的时间复杂度为:O(N),符合要求。

代码如下:

#include<stdio.h>

int missingNumber(int* nums, int numsSize) 
{
    //因为缺失了一个,数组nums中只有n个元素,数组元素个数numsSize = n
    
    //1. 求和 0 + 1 + 2 + 3 + 4 + …… + n-1 + n(共n+1项)
    //等差数列前 n 项和公式 Sn=n(a1+an)/2
    int sum = (numsSize + 1) * (0 + numsSize) / 2;
    //2. 减去数组中的所有数
    int i = 0;
    for (i = 0; i < numsSize; i++)
    {
        sum -= nums[i];
    }
    //3. 返回减后的结果
    return sum;
}

int main()
{
    int nums[9] = { 9,6,4,2,3,5,7,0,1 };
    int numsSize = sizeof(nums) / sizeof(nums[0]);  //求数组元素个数
    printf("missingNumber: %d\n", missingNumber(nums, numsSize));  //求缺失的数
    return 0;
}

运行结果:

image-20210729095610554

解法3:

对比观察:0 到 n 的所有整数,以及在此基础上缺失了一个数的数组 nums,有什么特点呢?

image-20210729101743706

异或的两个特性:

  1. 两个相等的数异或等于 0

  2. 任何一个数和 0 异或之后,还是这个数不变

  3. a ^ a = 0;0 ^ a = a;a ^ a ^ b = b

比如,原数组为:0 1 2 3

缺失一个数的数组:0 1 3

一一异或得到缺失的那个数:0 ^ 1 ^ 2 ^ 3 ^ 0 ^ 1 ^ 3 = 2

  • 我们利用异或的特性,两个相等的数异或等于 0,示例1和2的两个数组中除了缺失的那个数,其余数都出现了两次,将它们一起异或,就得到了一个 0,而 0 与缺失的那个数异或,还是等于原来的数。

  • 初始化 x = 0,用 x 跟 0 ~ n 的所有数一一异或后,再跟数组 nums 中所有数一一异或,得到结果就是缺失的那个数,该算法的时间复杂度是:O(N),符合要求

代码如下:

int missingNumber(int* nums, int numsSize) 
{
    //因为缺失了一个,数组nums中只有n个元素,数组元素个数numsSize = n
    
    int i = 0;
    int x = 0;
    //1. 与 0 ~ n 所有数异或
    for (i = 0; i <= numsSize; i++)
    {
        x ^= i;
    }
    //2 .再与数组中所有数异或
    for (i = 0; i < numsSize; i++)
    {
        x ^= nums[i];
    }
    return x;
}

大家赶紧动手去练一练吧!

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查哈希表中是否存在这个差值。 如果存在,则说明到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值