每日一解 缺失的第一个正数

题目 缺失的第一个正数

给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。

示例 1:
输入: [1,2,0]
输出: 3

示例 2:
输入: [3,4,-1,1]
输出: 2

示例 3:
输入: [7,8,9,11,12]
输出: 1

提示:
你的算法的时间复杂度应为O(n),并且只能使用常数级别的额外空间。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-missing-positive

思路

是个未排序的数组,那么第一反应当然是先排序再按序寻找正确的答案。但是提示里很快限定了O(n)的时间复杂度,再加上题目是寻找一个正整数,那么答案呼之欲出了,只有采用外部排序的方式才能达到效果。
但是,原本打算用哈希表存储数组结果,然后寻找缺失的正整数。结果要求用常数级别的空间,这意思就是在外部排序的基础上还要优化一下空间复杂度(然后我又不厚道地去瞄了眼官解的思路,这次官解的做法真的够巧妙的)。
这时候可以注意到,如果数列中没有1,那么输出必然是1。后续的2和3也是同理,这样其实可以得出一个结论,那就是长度为N的数组至多能包括1——N。那么可以用数组本身来判断缺失的正整数是多少:
举例说明一下这个方法:
输入: [1,3,2, 5]
我们检查到有一个1,那么就将数组的a[0]置为相反数即-1,然后检查到一个3,那么将数组的a[2]置为相反数,即-2,然后检查到一个-2,绝对值为2,那么将数组的a[1]置为相反数,也就是-3,最后加查到一个5,它比数组长度还大,那么不做操作。
此时数组的样子:
[-1,-3,-2,5]
此时我们依次遍历一下数组,找到第一个不是负数的数,它是数组中的第4个数,那么答案为4.
这样去做的话,只使用了原数组的空间,空间复杂度为1.

当然这里还有个小问题,如果遇到了负值怎么处理呢?之前说了长度为N的数组至多只能表示到N,那么将所有负数和0都置为N+1就不会影响这个算法的答案啦。

代码实现

依旧是直接放代码的实现:

class Solution {
    
    
public:
	int firstMissingPositive(vector<int>& nums) {
    
    
		int length = nums.size();
		int answer = 1;
		if (nums.size() == 0) {
    
    
			return answer;
		}
		for (int i = 0; i < length; i++) {
    
    
			nums[i] <= 0 ? nums[i] = length + 1: nums[i];
		}
		for (int i = 0; i < length; i++) {
    
    
			int absolute = abs(nums[i]);
			if (absolute <= length) {
    
    
				nums[absolute - 1] > 0 ? nums[absolute - 1] = 0 - nums[absolute - 1] : nums[i];
			}
		}
		for (int i = 0; i < length; i++) {
    
    
			if (nums[i] > 0) {
    
    
				return i + 1;
			}
		}
		return length + 1;
	}
};

基本上按着前面说的思路依次实现即可。

猜你喜欢

转载自blog.csdn.net/new_DYX/article/details/106978065
今日推荐