041J. First Missing Positive
https://leetcode.com/problems/first-missing-positive/
相关题目 268 448
Method Trivial:
Sort 自然是最暴力的方法。
class Solution {
public int firstMissingPositive(int[] nums) {
Arrays.sort(nums);
int res = 1;
for(int n : nums) {
if(n == res) {
res += 1;
}
}
return res;
}
}
Method Trivial:
如果能用空间 O(N),你会怎么做? 首先想到可以用 HashMap, 这个题一个更好的 HashMap 就是用数组。 直接类似桶排序即可。
class Solution {
public int firstMissingPositive(int[] nums) {
boolean[] buckets = new boolean[nums.length + 1];
for(int n : nums) {
if( n > 0 && n < nums.length + 1) {
buckets[n] = true;
}
}
for(int i = 1; i < buckets.length; i++ ) {
if(!buckets[i]) {
return i;
}
}
return buckets.length;
}
}
Method Best:
通过上面的代码,我们设想可以不新建数组,直接在原来的数组上进行同样的操作。
因此首先需要预处理数组,把不符合要求的数(非正数和大于 N 的),都处理掉。
令他们都是 N+1,这样我们通过数值本身就区别了符合要求的和不符合的。
将符合要求的数直接在原地进行方法 1 中的排序。如何将原位的数组剥离成两个独立
的数组呢?答案是利用正负号。
比如 nums[2] = 3, nums[3] = 2.
nums[3] = -2, 负号意味着 idx 3 已经有了,当我们运行到 idx = 3 时,
我们取绝对值 2, 这是进入到 key 中。然后找到 num[2] 标记为 -3。这个负号说明
被标记过了。
由于我们没有 N + 1 长度的数组,只好把各个位置都移一位到 i - 1。
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) {
nums[i] = N + 1;
}
}
for(int i = 0; i < N; i++){
int num = Math.abs(nums[i]);
if(num > N ) continue;
num --;
if( nums[num] > 0){ // 这是为了防止有重复的数 导致负负得正
nums[num] *= -1;
}
}
for(int i = 0; i < N; i++){
if(nums[i] >= 0){
return i + 1;
}
}
// 如果全部都被标记过,那么就返回 N + 1.
return N + 1;
}
}
Last updated
Was this helpful?