Given an unsorted integer array, find the first missing positive integer.
For example,
Given [1,2,0]
return 3
,
and [3,4,-1,1]
return 2
.
Your algorithm should run in O(n) time and uses constant space.
题意:
给定了一个无序数组,要求找到第一个缺失的正整数.如1,2,4,5的第一个缺失的正整数是3.要求时间复杂度为o(n) 空间复杂度为o(1)
思路:
第一种是排序,时间复杂度为O(nlgn) 不行
第二种是hash查找 对每一个数字都用额外空间找到正确的位置. 然后一次遍历找到第一个缺失的正整数. 时间复杂度为O(n) 但是空间复杂度为O(n) 也不符合题目要求
第三种直接在输入数组上进行交换操作, 使得每个数字通过交换能在正确的位置上.如3,1,7,2 这组数字第一次交换后得到7,1,3,2 数字3放置在了正确的位置.
这种时间复杂度为O(n) 而且只需要常数辅助空间. 但我认为这种方法依然不复合题目要求,因为它破坏了原始数组. 它其实也类似于hash, 需要O(n)的空间,只不过这O(n)的空间借用了原始输入数组上的.
目前我还没找到即不破坏原始数组,空间复杂度又为O(1)的方法
代码1(hash法):
class Solution { public: int firstMissingPositive(vector<int>& nums) { if (nums.size() == 0) return 1; auto it_max = std::max_element(nums.begin(), nums.end()); auto it_min = std::min_element(nums.begin(), nums.end()); vector<bool> vec(*it_max - *it_min, false); for (auto elem : nums) vec[elem - *it_min] = true; for (auto it = 1; it <= *it_max; ++it) { if (it < *it_min || (it > 0 && !vec[it - *it_min])) return it; } return *it_max > 0 ? *it_max + 1 : 1; } private: };
代码2(直接在原数组上进行交换, 空间代价为o(1))
class Solution { public: int firstMissingPositive(vector<int>& nums) { if (nums.empty()) return 1; auto begin = getFirstPositivePos(nums); if (*begin < 0) return 1; for (auto it = begin; it != nums.end(); ) { auto realPos = begin + *it - 1; if (realPos < nums.end() && realPos != it && *realPos != *it) iter_swap(it, realPos); else ++it; } int index = 1; for (auto it = begin; it != nums.end(); ++it, index++) { if (index != *it) return index; } return index; } private: vector<int>::iterator getFirstPositivePos(vector<int>& nums) { auto first = nums.begin(); auto last = nums.end()-1; while (true) { while (first < last && *first <= 0 ) ++first; while (first < last && *last > 0) --last; if (first < last) iter_swap(first, last); else break; } return first; } };