Leetcode 268 缺失数字

题目要求


想法

想法一:

  使用高斯求和公式求出0->n中所有数字之和,然后用所有数字之和减去序列中的数,最后得到的便是序列中缺少的那个数。最开始的想法是想用哈希表,但考虑到用哈希表的话,空间复杂度O(N),时间复杂度O(N),想去降低空间复杂度O(N),便想到了使用高斯求和的方法。

代码:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int length = nums.size(),sum;
        if(length%2==0) sum=(1+length)*(length/2);
        else sum=(1+length)*(length/2)+length/2+1;
        for(int i=0;i<nums.size();i++)
            sum-=nums[i];
        return sum;
    }
};

运行结果:

总结与反思:

  高斯求和方法无论在时间和空间上都具有非常好的效率,但是如果输入的n非常大时,求和会很容易溢出int的表示范围。虽然在这个题上,高斯求和的方法通过了,但是还是不太建议使用高斯求和的方法。


想法二:

  位运算,这是我从Leetcode题解和csdn博客上看到的方法,感觉牛人还是多啊,哈哈。因为异或运算满足交换律和结合律,对相同的数进行两次异或运算结果还是自己(example: x^y^y = x),利用这个性质我们可以对0->n和序列进行位运算,最后得到的结果就是缺失的值,因为缺失的值在0->n和序列中只出现了一次,其他的值都出现了两次,相当于缺失的值对其他所有的值进行了两次异或运算,所以得到的还是缺失的值。

代码:

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

运行结果:

总结与反思:

  相比较两个想法的消耗时间是比较接近的,区别是一个要进行加法运算另一个不进行加法运算,这样就避免了因为求和而导致的数值溢出问题。其他思路比如排序,虽然比较容易想,但是时间复杂度最低O(nlogn),所以就不再考虑。


Leetcode 448 找到数组中所有消失的数 后更。

想法三

  遍历数组,用数组中对应的值,去相应的index上加上数组的size()。比如[1,1,2],nums[0]=1,那么nums[1]加上3,nums[2]=2,那么nums[2]加上3,nums[1]=1,那么nums[1-1]加上3,最后得到[1,7,5]。而nums[0]<3,所以缺1,对于多余的数原理相同。虽然最后的实现有一点不同。

代码

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        nums.push_back(nums[0]);
        for(int i=0;i<nums.size();i++){
            int index = nums[i]%nums.size();
            nums[index] += nums.size();
        }
        int i;
        for(i=0;i<nums.size();i++){
            if(nums[i]<nums.size())
                break;
        }
        return i;
    }
};

运行结果

总结与反思

  题做多了之后,多去总结,有很多方法是通用的,一定要做到一题多解。加油。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值