题目
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
思路
方法一:空间复杂度为O(n),思路正确,但是不满足题意,但是LeetCode能过(诶嘿~)
从最小的正整数1开始,依次判断2、3、4…直到数组的长度N是否在数组中,如果不在,则找到了缺失的最小正整数
class Solution {
public int firstMissingPositive(int[] nums) {
int len = nums.length;
Set<Integer> hashSet = new HashSet<>();
for (int num : nums) {
hashSet.add(num);
}
for (int i = 1; i <= len ; i++) {
if (!hashSet.contains(i)){
return i;
}
}
return len + 1;
}
}
方法二:将数组视为哈希表
因为要找的数一定是在[1,N+1]
之间,所以可以就把原始的数组当做哈希表来使用
N+1
是因为当前面都没找到的时候,返回最后一个数的下一个数字
哈希表的思想为,将数值为 i
的数映射到下标为 i - 1
的位置(即数值比下标大1)
先按照哈希表的映射关系整理一遍数组,然后再遍历一次数组,第 1 个遇到的它的值不对应下标的那个数,就是我们要找的缺失的第一个正数
1.nums[i] > 0 && nums[i] <= len
表示范围1 ~n
的正整数
2.nums[i] != i + 1
表示当前位置的值不对(只有值不对,才会去继续判断当前位置的数是不是在应该在的位置上)
3.nums[nums[i] - 1] != nums[i]
表示当前i
位置的数没有在应该在的位置上(数值k
应该在索引为k-1
的位置上),即数nums[i]
没有在下标为nums[i] - 1
的位置上
class Solution {
public int firstMissingPositive(int[] nums) {
int len = nums.length;
for (int i = 0; i < len; i++) {
while (nums[i] > 0 && nums[i] <= len && nums[i] != i + 1 && nums[i] != nums[nums[i] - 1]) {
swap(nums, nums[i] - 1, i);
}
}
for (int i = 0; i < len; i++) {
if (nums[i] != i + 1) {
return i + 1;
}
}
// 都正确则返回数组长度 + 1
return len + 1;
}
private void swap(int[] nums, int index1, int index2) {
int temp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = temp;
}
}