leetcode 41 缺失的第一个正数
41 缺失的第一个正数
给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。
示例 1:输入: [1,2,0]输出: 3
示例 2:输入: [3,4,-1,1]输出: 2
示例 3:输入: [7,8,9,11,12]输出: 1
提示:你的算法的时间复杂度应为O(n),并且只能使用常数级别的额外空间。
思路1:
hash 表, 从小到大枚举检查1 ~ nums.size()是否在数组中存在,如果不存在则说明我们找到了最小的不存在数字。
class Solution { public: int firstMissingPositive(vector<int>& nums) { unordered_set<int> nums_set; for(int n : nums) nums_set.insert(n); for(int i = 1; i <= nums.size(); i++) if(!nums_set.count(i)) return i; return nums.size() + 1; } };
思路2:先排序再找
class Solution { public: int firstMissingPositive(vector<int>& nums) { sort(nums.begin(), nums.end()); int ans = 1; for(int num : nums){ if(num == ans) ans++; } return ans; } };
思路3:利用原数组哈希
我们考虑使用原数组实现哈希表。我们将映射公式设为nums[i] = i+1。
即下标为0,存放1;下标为1,存放2......假设nums数组长度为n,那么最后的答案应该在[1,n+1]范围内,且只有当nums为存放的为1-n内的所有正整数时,答案才为n+1。
我们遍历nums,判断nums[i],当它的值范围在[1,n]中,就将它与nums[nums[i]-1]进行互换,
此时还需要判断nums[nums[i]-1]是不是与nums[i]已经相等了,这时就是遇到了重复的元素,pass。
遍历完之后,我们再一次遍历更改后的nums数组,当nums[i] != i+1,返回i+1即可,若遍历结束之后没有返回,返回n+1即可。
也就是,第一次遍历将数据归位,
第二次遍历检查,谁缺失了即可
class Solution { public: int firstMissingPositive(vector<int>& nums) { int n = nums.size(); for(int i = 0; i < n; i++){ while(nums[i] >= 1 && nums[i] <= n && nums[i] != nums[nums[i]-1]) swap(nums[i], nums[nums[i]-1]); } for(int i = 0; i < n; i++) if(nums[i] != i+1) return i+1; return n+1; } };