【LeetCode 41】力扣困难算法:缺失的第一个正数
题目:给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
输入:nums = [1,2,0]
输出:3
解释:范围 [1,2] 中的数字都在数组中。
算法思路:这个算法的关键是尝试将数组中的每个正整数放到它应该在的位置上,然后检查哪个位置的数字不在正确的位置上。
1. 整理数组:
我们遍历数组,对于每个元素,如果它是一个在1到数组长度(n)之间的正整数,就尝试将它放到数组的正确位置上。比如,如果一个元素是3,我们就将它和数组中索引为2(因为索引是从0开始的)的元素交换,这样数字3就放到了它应该在的位置上。重复这个过程,直到每个数字都放到了正确的位置上,或者没有更多的数字可以交换了。
2. 找出缺失的最小正整数:
整理完数组后,我们再次遍历数组,看看哪个位置的数字不是它应该的值(即索引加1)。比如,如果索引0上的数字不是1,那么1就是缺失的最小正整数。
如果所有的位置都正确,那么缺失的最小正整数就是数组长度加1。
代码步骤:
步骤1:通过交换元素,将每个数字放到数组中正确的位置上。
步骤2:检查数组,找出哪个位置的数字不在正确的位置上,这个位置的索引加1就是我们要找的缺失的最小正整数。
为什么这样做呢?
这样做的好处是我们不需要额外的空间来存储数据,直接在原数组上操作,既节省了空间,又简化了操作。通过这种方法,可以快速地找到缺失的最小正整数,而不需要一个一个地去检查每个可能的正整数。
时间复杂度是: O ( n )
空间复杂度是: O ( 1 )
算法的局限性:
这个方法假设数组中至少有一个正整数,而且所有的正整数都不会太大,以至于我们能够通过交换数组中的元素来找到答案。如果数组太大,或者需要检查的正整数太多,这个方法可能会稍微慢一些。
我的 Java 代码:
class Solution {
public int firstMissingPositive(int[] nums) {
// 1.把正整数元素置换到正确的位置,把1放到第0位,2放到第1位,5放到第4位......负数不管
int n = nums.length;
for (int i = 0; i < n; i++) {
while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) { //注意该元素要满足三个条件
int t = nums[i];
nums[i] = nums[nums[i] - 1];
nums[t-1] = t;
}
}
// 2.寻找缺失的最小正整数
for (int i = 0; i < n; i++) {
if (nums[i] != i + 1) {
return i + 1;
}
}
// 3.如果数组是连续的正整数,结果为n+1
return n + 1;
}
}

浙公网安备 33010602011771号