题目
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
数据范围
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
测试样例
示例1
java
输入:nums = [1,2,0]
输出:3
解释:范围 [1,2] 中的数字都在数组中。
示例2
java
输入:nums = [3,4,-1,1]
输出:2
解释:1 在数组中,但 2 没有。
示例3
java
输入:nums = [7,8,9,11,12]
输出:1
解释:最小的正数 1 没有出现。
题解(哈希)
java
public static int firstMissingPositive(int[] nums) {
int len= nums.length;
for(int i=0;i<len;i++){
if(nums[i]<=0){
nums[i]=len+1;
}
}
for(int i=0;i<len;i++){
int r=Math.abs(nums[i]);
if(r>=1&&r<=len&&nums[r-1]>0){
nums[r-1]*=-1;
}
}
for(int i=0;i<len;i++){
if(nums[i]>0){
return i+1;
}
}
return len+1;
}
思路
这一道题,从各个方面来说,博主认为难点并不在于其逻辑过程,而是有没有这种思路。反正博主在这之前从来没有做过为了节约空间使用题目给的数组,从而达到常数级的空间复杂度。在我看来这是掩耳盗铃,因为你既然用了题目给的数组,空间复杂度已经到了O(n),除开这个数组算空间复杂度,有一种为了出题而出题,高中的那些恶心人的数学题的感觉。
说回题目,怎么达到常数级的空间复杂度,理论上不可能,但如果你默认你默认,题目给你的数组不算空间复杂度,然后基于这一点,使用这个数组(想到这里就难崩),就可以实现。
当然这道题也不仅限于逻辑奇怪,它还是提供了两个比较优秀的思路。
第一点,我们还要想通一个逻辑,N个数,除开这些的最小正整数一定是1-n+1,我们不妨假设N个数刚好就是1-n,那么最小正整数就是n+1,如果N个数有一个数不在1-n,1-n的位置就会被空出相应个数,我们的答案也同样在这里面。
第二点,原数组已经有数了,怎么在此基础上用哈希?这一点非常漂亮,使用了正负号作为哈希标记。
大概细节就这些,具体逻辑我引用官方题解的部分文字,就不重复描述了,毕竟博主也是看的题解,不是自己思路不想描述太多。
仔细想一想,我们为什么要使用哈希表?这是因为哈希表是一个可以支持快速查找的数据结构:给定一个元素,我们可以在 O(1) 的时间查找该元素是否在哈希表中。因此,我们可以考虑将给定的数组设计成哈希表的「替代产品」。
实际上,对于一个长度为 N 的数组,其中没有出现的最小正整数只能在 [1,N+1] 中。这是因为如果 [1,N] 都出现了,那么答案是
N+1,否则答案是 [1,N] 中没有出现的最小正整数。这样一来,我们将所有在 [1,N]
范围内的数放入哈希表,也可以得到最终的答案。而给定的数组恰好长度为 N,这让我们有了一种将数组设计成哈希表的思路:
我们对数组进行遍历,对于遍历到的数 x,如果它在 [1,N] 的范围内,那么就将数组中的第 x−1 个位置(注意:数组下标从 0
开始)打上「标记」。在遍历结束之后,如果所有的位置都被打上了标记,那么答案是 N+1,否则答案是最小的没有打上标记的位置加 1。
那么如何设计这个「标记」呢?由于数组中的数没有任何限制,因此这并不是一件容易的事情。但我们可以继续利用上面的提到的性质:由于我们只在意
1,N\] 中的数,因此我们可以先对数组进行遍历,把不在 \[1,N\] 范围内的数修改成任意一个大于 N 的数(例如 N+1)。这样一来,数组中的所有数就都是正数了,因此我们就可以将「标记」表示为「负号」。算法的流程如下: 我们将数组中所有小于等于 0 的数修改为 N+1; 我们遍历数组中的每一个数 x,它可能已经被打了标记,因此原本对应的数为 ∣x∣,其中 ∣∣ 为绝对值符号。如果 ∣x∣∈\[1,N\],那么我们给数组中的第 ∣x∣−1 个位置的数添加一个负号。注意如果它已经有负号,不需要重复添加; 在遍历完成之后,如果数组中的每一个数都是负数,那么答案是 N+1,否则答案是第一个正数的位置加 1。 作者:力扣官方题解 链接:https://leetcode.cn/problems/first-missing-positive/solutions/304743/que-shi-de-di-yi-ge-zheng-shu-by-leetcode-solution/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。