寻找[0, n] 消失的一个元素

这篇博客介绍了四种寻找序列中缺失数字的方法:排序、数组标记、位运算和等差数列。通过排序和数组标记实现,时间复杂度为O(nlogn)和O(n),而位运算和等差数列方法在O(n)时间内完成,其中位运算利用异或性质,等差数列方法结合数学公式。提供了优化后的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇博客的知识体系来自labuladong的汇总,对其精妙的方法极为惊叹,特此记录一下,如需查看原文请点击labuladong。

题目:给定一个包含0,1,2,3…,n中的n个序列,找出0…n中没有出现在序列中的那个数。

方法一:排序 O(nlogn)+O(1)

采用排序的方法,然后遍历一遍找到缺失的数字。该方法的时间复杂度为O(n),空间复杂度为O(1)。

方法二:数组方法 O(n)+O(n)

另外开辟数组,如果这个数组出现过,标记一下,找到没有标记的数字。该方法的时间复杂度O(n),空间复杂度为O(n),典型的空间换时间的复杂度。

方法三:位运算 O(n)+O(1)

在我们学习异或运算,相同数字的两个数字异或为0,那么我们异或[0, n]的数据,再异或需要求出[0, n]缺失数据的数组,异或的过程中会出现两个一样的数据相互抵消,最终只剩下缺失值。
代码源自 labuladong

int missingNumber(int[] nums) {
    int n = nums.length;
    int res = 0;
    // 先和新补的索引异或一下
    res ^= n;
    // 和其他的元素、索引做异或
    for (int i = 0; i < n; i++)
        res ^= i ^ nums[i];
    return res;
}

方法四:等差数列 O(n)+O(1)

这个方法很容易忽略,我们利用等差公式求出等差数列前n项和,然后减去给出缺失值的数组中的数据和,就是我们要的缺失值。但是该方法涉及乘法可能导致数据溢出,所以我们就需要优化该方法。
代码源自labuladong

int missingNumber(int[] nums) {
    int n = nums.length;
    // 公式:(首项 + 末项) * 项数 / 2
    int expect = (0 + n) * (n + 1) / 2;

    int sum = 0;
    for (int x : nums) 
        sum += x;
    return expect - sum;
}

优化:

我们在遍历的时候一边求和一边减算,具体实现方法请看代码。
代码源自labuladong

public int missingNumber(int[] nums) {
    int n = nums.length;
    int res = 0;
    // 新补的索引
    res += n - 0;
    // 剩下索引和元素的差加起来
    for (int i = 0; i < n; i++) 
        res += i - nums[i];
    return res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值