题目选自 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);
}
};
在此输入正文