寻找缺失的数

题目选自 lintcode


给出一个包含 0 .. N 中 N 个数的序列,找出0 .. N 中没有出现在序列中的那个数。
样例
N = 4 且序列为 [0, 1, 3] 时,缺失的数为2。
注意
可以改变序列中数的位置。
挑战
在数组上原地完成,使用O(1)的额外空间和O(N)的时间。

解法1:空间O(1),时间复杂度O(n)

首先将0 - N求和,依次减掉序列中的数,得到最终的数。

class Solution {
public:
    /**    
     * @param nums: a vector of integers
     * @return: an integer
     */
    int findMissing(vector<int> &nums) {
        // write your code here
        int size = nums.size();
        int missnum= size * (size + 1) / 2;
        if(size == 0)
            return 0;

        for(int i = 0; i < size; i++)
        {
            missnum -= nums[i];
        }
        return missnum;
    }
};

问题:当序列很大时,会出现溢出问题,longlongint为2^64,要算1/2*N*(N+1),大约2^32时便超出范围,产生溢出。可以采用牺牲空间的方法,解决此问题。利用一张N+1的表,初始化为0,如序列中有的置为1,遍历一遍后,剩下为零的数即为所需。耗用空间为2^32/8/1024/1024/1024 = 0.5 GB。

解法2:空间O(n+1),时间O(n)

开辟N个元素的数组,初始化为0,利用序列中的数据作为索引,对应数组位置置1,遍历一遍0所在的位置就是要找的数。

class Solution {
public:
    /**    
     * @param nums: a vector of integers
     * @return: an integer
     */
    int findMissing(vector<int> &nums)
    {
        // write your code here
        int size = nums.size();
        int missnum = 0;
        vector <bool> listall(size+1); 
        if(size == 0)
            return 0;
        for(auto pd = nums.begin(); pd != nums.end(); pd++)
        {
            listall[*pd] = 1;
        }
        for(auto p = listall.begin(); p != listall.end(); p++)
        {
            if(*p == 0)
            {      
                missnum = p - listall.begin();
                break;   
            } 
        }
        return missnum;
    }
};

问题

以上两种方法只适用于给定数组只有正整数,并且不重复出现,若出现以上问题,就会需要修改以上算法,使得算法更具普适性。

class Solution {
public:
    /**    
     * @param A: a vector of integers
     * @return: an integer
     */
    int firstMissingPositive(vector<int> A) {
        // write your code here
        sort(A.begin(), A.end(),less<int>());
        int size_A = A.size();

        if(size_A == 0)
            return 1;

        int fast = 1;
        int slow = 1;
        int temp = A[0];
        int newSize = 0;
        for(int j = 0; j < size_A; j++)
        {
            if(temp != A[fast])
            {
                A[slow] = A[fast];
                slow++;
                newSize++;
                temp = A[slow - 1];
            }
            fast++;
        }

        int result = 0;
        int count = 0;
        int i;
        for(i = 0; i < newSize; i++)
        {
            if(A[i] <= 0)
            {
                count++;
                continue;
            }
            if(A[i] != (i - count + 1))
            {
                break;
            }
        }
        return (i - count + 1);
    }
};

在此输入正文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值