DESC:
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
进阶:你可以实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案吗?
示例 1:
输入:nums = [1,2,0]
输出:3示例 2:
输入:nums = [3,4,-1,1]
输出:2示例 3:
输入:nums = [7,8,9,11,12]
输出:1提示:
0 <= nums.length <= 300
-231 <= nums[i] <= 231 - 1来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-missing-positive
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
CODE1:
JAVA:
class Solution { public int firstMissingPositive(int[] nums) { int n = nums.length; for (int i=0; i<n; i++) { if (nums[i]<=0) { //重点,注意包含等于号 nums[i] = n+1; } } for (int i=0; i<n; i++) { int val = Math.abs(nums[i]); //重点,注意取绝对值 if (val <= n) { nums[val-1] = -Math.abs(nums[val-1]); //重点,注意取绝对值,防止同一位置重复打标 } } for (int i=0; i<n; i++) { if (nums[i]>0) { return i+1; } } return n+1; } }
Python
class Solution: def firstMissingPositive(self, nums: List[int]) -> int: if not nums or len(nums) == 0: return 1 n = len(nums) res = n+1 for i in range(n): if nums[i]<=0: nums[i] = res for i in range(n): val = abs(nums[i]) if val <= n: nums[val-1] = -1*abs(nums[val-1]) for i in range(n): if nums[i] > 0: return i+1 return res
NOTES:
- 打标,数组长度为n,结果肯定在[1,n+1]之间,将小于等于0的数都转换为n+1,此时数组区间是>=1,方便后面打标;
- 遍历数组,针对小于等于n的元素,在其本该属于的索引位置进行打标,转换为负数,如x=3,将index=2的位置元素的绝对值转为负数,标记3这个位置元素存在,但要注意取绝对值转为负数,防止这个位置被打多次,负正轮换;结束后,数组中元素本该在的位置都标记上了负数。
- 遍历数组,查找第一个不为负的位置,即表示该位置没有对应的元素打标,即为缺失值。每次遍历都是O(n)的时间复杂度。
CODE2:
JAVA:
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[nums[i]-1] != nums[i]) { int temp = nums[nums[i]-1]; nums[nums[i]-1] = nums[i]; nums[i] = temp; } } for (int i=0; i<n; i++) { if (i+1!=nums[i]) { return i+1; } } return n+1; } }
NOTES:
- 递归交换,遍历数组元素,将[1,n]间的元素放在其对应的位置,与其该存在的位置进行交换,但要避免相等重复交换死循环。如[2,3,1],i=0时,x=2,2和3互换后[3,2,1], x=3,仍然可继续互换为[1,2,3];直到不需要互换或x不在区间内
- 最后遍历数组,判断对应位置的元素知否为正确值,不是,则该位置为缺失的正数。