leetcode 41. 缺失的第一个正数
问题描述
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
示例 1:
输入: [1,2,0]
输出: 3
示例 2:
输入: [3,4,-1,1]
输出: 2
示例 3:
输入: [7,8,9,11,12]
输出: 1
说明:
你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。
代码1
首先给一个空间复杂度为\(O(N)\)的算法,用map数组记录[1,n]之间的数字是否出现,大于n的数字与小于0的数字不用考虑,因为这肯定不是缺少的第一个正数,最后我们返回的是n+1,是考虑例子[1,2,0]这种情况。
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size(),i;
vector<int> map(n,0);
for(i = 0; i < n; i++)
{
if(nums[i] <= n && nums[i] > 0)
map[nums[i]-1] = 1;
}
for(i = 0; i < n; i++)
{
if(map[i] == 0)
return i+1;
}
return n+1;
}
};
结果
执行用时 :12 ms, 在所有 C++ 提交中击败了29.88%的用户
内存消耗 :12.2 MB, 在所有 C++ 提交中击败了5.19%的用户
代码2
当然题目要求我们使用常数的空间复杂度,既然不能建立新的数组,那么我们只能覆盖原有数组,我们的思路是把1放在数组第一个位置nums[0],2放在第二个位置nums[1],即需要把nums[i]放在nums[nums[i] - 1]上,那么我们遍历整个数组,如果nums[i] != i + 1, 而nums[i]为整数且不大于n,另外nums[i]不等于nums[nums[i] - 1]的话,我们将两者位置调换,如果不满足上述条件直接跳过,最后我们再遍历一遍数组,如果对应位置上的数不正确则返回正确的数。注意for循环里面是while循环而不是if,是让正确的数在正确的位置上为止。
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size(),i;
for(i = 0; i < n; i++)
{
while(nums[i] <= n && nums[i] > 0 && nums[i] != nums[nums[i]-1])
swap(nums[nums[i]-1],nums[i]);
}
for(i = 0; i < n; i++)
{
if(nums[i] != i+1)
return i+1;
}
return n+1;
}
};
结果
执行用时 :8 ms, 在所有 C++ 提交中击败了29.88%的用户
内存消耗 :12.3 MB, 在所有 C++ 提交中击败了5.19%的用户