思路很简单,找出最大正数和最小正数,然后建立一个数组visit,记录从最小正数到最大正数之间哪些数有,哪些数没有。最后遍历一下visit就行了。不过visit的长度需要注意一下。举个简单的例子,nums = [1,4,5,1000]。很显然,缺失的最小整数为3。在new一个数组visit记录1到1000哪些数存在与否有点技巧。你可以直接new长度1000的数组,但如果最大元素太大,内存开销会不足。此时,你只需要new一个长度为 4-1+1长度的数组。为什么不是new一个长度为 5-1+1长度的数组呢?假设nums中原来的数是连续的,nums=[1,2,3,4],所以如果nums中存在缺失,一定就在前4个数(nums中正数个数的长度)里面。
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int maxele = -INT_MAX;//记录最大正数
int minele = INT_MAX;//记录最小正数
int n = 0;//记录正数的个数
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > 0) {
n++;
if (nums[i] > maxele)
maxele = nums[i];
if (nums[i] < minele)
minele = nums[i];
}
}
if (minele > 1)
return 1;
int temp = -1;
/*寻找nums中减去最小元素的值小于正数个数n的最大元素。
如nums = [1,2,4],正数个数n=3,4-1=n,2-1<n,1-1<n。2为查找得到的元素。
new一个动态数组,len=2-1+1为数组长度*/
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > 0 && nums[i] - minele < n && nums[i] - minele > temp)
temp = nums[i] - minele;
}
//visit数组长度
int len = temp + 1;
int *visit = new int[len];
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > 0 && nums[i] - minele < n)
visit[nums[i] - minele] = 1;
}
//如果在visit里面,可以找到一个数缺失,return这个数
for (int i = 0; i < len; i++)
if (visit[i] != 1)
return i + minele;
//否则,这个数在visit外,越界1
return len + minele;
}
};