题目:
Given an unsorted integer array, find the smallest missing positive integer.
Example 1:
Input: [1,2,0]
Output: 3
Example 2:
Input: [3,4,-1,1]
Output: 2
Example 3:
Input: [7,8,9,11,12]
Output: 1
Note:
Your algorithm should run in O(n) time and uses constant extra space.
解法1:
不考虑空间复杂度,用set将所有的正数存进去,找到最大值,从1开始到最大值依次找,如果set中没有,即为首个缺失的正数,遍历完成后,说明缺失的正数是最大值加1
c++:
class Solution {
public:
int firstMissingPositive(vector& nums) {
int maxNum = 0;
unordered_set s;
for(int num : nums){
if(num > 0){
s.insert(num);
maxNum = max(maxNum, num);
}
}
for(int i = 1; i <= maxNum; ++i){
if(!s.count(i)) return i;
}
return maxNum + 1;
}
};
解法2:
桶排序
考虑到时间复杂度O(n)不能用常规排序,由于不能用额外空间,即空间复杂度为O(1),即我们要利用原来的数组
考虑桶排序,即nums[0]放1,nums[1]放2,即需要把nums[i]放在nums[nums[i] - 1]上,怎么实现呢
例:
Input: [3,4,-1,1]
Output: 2
第一次:num[i] = 3,它不应该在0号位置,而应该在2号位置,即第三个数,交换nums[i] ,nums[nums[i]-1],结果-1,4,3,1
继续循环,num[i] = -1,退出循环
第二次:num[i] = 4,它不应该在1号位置,而应该在3号位置,即第4个数,交换nums[i] ,nums[nums[i]-1],结果-1,1,3,4
继续循环,num[i] = 1,它不应该在1号位置,而应该在0号位置,即第1个数,交换nums[i] ,nums[nums[i]-1],结果1,-1,3,4
继续循环,num[i] = -1,退出循环
第三次:num[i] = 3,它的位置正确,退出循环
第四次:num[i] = 4,它的位置正确,退出循环
再一次遍历数组,即可找到缺失的2
Input: [7,8,9,11,12]
Output: 1
第一次:num[i] = 7,它不应该在0号位置,而应该在6号位置,即第7个数,但是数组没有这么大,不作处理
剩下的情况类似都是不作处理
再一次遍历数组,即可找到缺失的1
c++:
class Solution {
public:
int firstMissingPositive(vector& nums) {
int n = nums.size();
for(int i = 0; i < n; i++){
while(nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i]-1]){
swap(nums[i] ,nums[nums[i]-1]);
}
}
for(int i = 0; i < n; ++i){
if(nums[i] != (i + 1)) return i + 1;
}
return n + 1;
}
};
java:
注意java中没有swap函数,需要我们自己写,另外java是值传递,所以我们要传三个参数进去
private void swap(int[] nums, int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
另外一种不用临时变量的写法
private void swap(int[] nums, int i, int j){
nums[i] ^= nums[j];
nums[j] ^= nums[i];
nums[i] ^= nums[j];
}
class Solution {
public int firstMissingPositive(int[] nums) {
int n = nums.length;
for(int i = 0; i < n; i++){
while(nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i]-1]){
swap(nums, i ,nums[i]-1);
}
}
for(int i = 0; i < n; ++i){
if(nums[i] != (i + 1)) return i + 1;
}
return n + 1;
}
private void swap(int[] nums, int i, int j){
nums[i] ^= nums[j];
nums[j] ^= nums[i];
nums[i] ^= nums[j];
}
// private void swap(int[] nums, int i, int j){
// int temp = nums[i];
// nums[i] = nums[j];
// nums[j] = temp;
// }
}
python:
注意不能用nums[i] ,nums[nums[i]-1] = nums[nums[i]-1], nums[i]
首先会生成nums[nums[i]-1], nums[i],然后将nums[nums[i]-1]赋给nums[i] ,然后将nums[i]赋给,nums[nums[i]-1],但在第一次赋值的过程中nums[i] 的值就变了,导致错误
class Solution(object):
def firstMissingPositive(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
for i in xrange(n):
while nums[i] > 0 and nums[i] <= n and nums[i] != nums[nums[i]-1]:
tmp = nums[i]-1
#nums[i] ,nums[nums[i]-1] = nums[nums[i]-1], nums[i]
nums[i] ,nums[tmp] = nums[tmp], nums[i]
#print nums
for i in xrange(n):
if nums[i] != (i + 1): return i + 1
return n + 1