class Solution { public: int firstMissingPositive(int A[], int n) { if (A == NULL || n < 1) return 1; size_t len = (size_t)n + 1; vector<bool> bits(len, false); for (int i=0; i<n; i++) { if (A[i] < 0 || A[i] > n) continue; bits[A[i]] = true; } int miss = 1; while (miss <= INT_MAX) { if (!bits[miss]) return miss; if (miss == INT_MAX) { cout<<"no missing positive"<<endl; break; } miss++; } bits.clear(); return 0; } int firstMissingPositive2(int A[], int n) { if (A == NULL || n < 1) return 1; unordered_map<int, int> mark; for (int i=0; i<n; i++) { mark[A[i]] = 1; } int miss = 1; while (miss <= INT_MAX) { if (mark.find(miss) == mark.end()) return miss; if (miss == INT_MAX) { cout<<"no missing positive"<<endl; return 0; } miss++; } return miss; } int firstMissingPositive3(int A[], int n) { if (A == NULL || n < 1) return 1; for (int i = 0; i<n; i++) { if (A[i] <= 0) A[i] = n + 1; } for (int i=0; i<n; i++) { int cur = A[i] < 0 ? -A[i] : A[i]; if (cur <= n) A[cur - 1] = A[cur - 1] < 0 ? A[cur - 1] : -A[cur - 1]; } int miss = 1; for (int i=0; i<n; i++) { if (A[i] > 0) break; miss++; } return miss; } };
心烦,因为要找出数组A[n]中第一个缺失的整数,如果数组中有元素大于n那么这个数组必定至少缺失了一个数,因为如果A[n]包含[1,n]那么刚刚n个数,一个不少,且每个数小于n,如果某个元素大于n了,则中间肯定有间隙存在,否则元素个数将大于n。利用这一特征我们可以把负数和大于n的数都置为n+1这样在下一次扫描时可以忽略它们。
解法三存在一个问题,当n=INT_MAX且有负数存在时会出错。
第二轮:
解法三应该是从disscus上搞过来的,这个跟使用常数空间找一个无序数组(数组元素范围小于长度值)中的重复值类似,可以使用负数作为标记。实际上是使用了每个元素的符号位这样的一系列1bit的存储空间。反正已经将数组破坏掉了,还可以这样写避免数值溢出:
1 class Solution { 2 public: 3 int firstMissingPositive(vector<int>& nums) { 4 int len = nums.size(); 5 int idx = 0; 6 for (idx = 0; idx < len; idx++) { 7 if (nums[idx] == 1) { 8 break; 9 } 10 } 11 if (idx == len) { 12 return 1; 13 } 14 15 for (int i=0; i<len; i++) { 16 nums[i] = max(1, nums[i]); 17 } 18 19 for (int i=0; i<len; i++) { 20 idx = abs(nums[i]) - 1; 21 if (idx >= len) { 22 continue; 23 } 24 if (nums[idx] > 0) { 25 nums[idx] = -nums[idx]; 26 } 27 } 28 idx = 0; 29 while (nums[idx] < 0 && idx < len) idx++; 30 return idx + 1; 31 } 32 };
把小于等于0的数全部置为1,当然首先要检测一下1是否存在。