LeetCode 41. First Missing Positive

Given an unsorted integer array nums. Return the smallest positive integer that is not present in nums.

You must implement an algorithm that runs in O(n) time and uses O(1) auxiliary space.

Example 1:

复制代码
Input: nums = [1,2,0]
Output: 3
Explanation: The numbers in the range [1,2] are all in the array.

Example 2:

复制代码
Input: nums = [3,4,-1,1]
Output: 2
Explanation: 1 is in the array but 2 is missing.

Example 3:

复制代码
Input: nums = [7,8,9,11,12]
Output: 1
Explanation: The smallest positive integer 1 is missing.

Constraints:

  • 1 <= nums.length <= 105
  • -231 <= nums[i] <= 231 - 1

这题给了一个unsorted array of integers,可正可负,要求求出这个数组里没有的第一个正数。

最直观的方法就是把这个数组变成一个set,然后从1开始看它在不在这个set里。然而题目要求不能用extra space,就,不会。

hint说可以想想怎么把hashset换个方式hash一下,想不到。直接看了答案,牛,但是思路虽然简单但是写起来也kind of复杂。

大概的思路就是没有出现的第一个正数一定是在[1, len]之间,于是我们就可以把出现过的数字都hash到数组里对应的index上,比如数字n就可以hash到index n - 1。为啥是i - 1呢是因为最大可能是len,但是index是len - 1。所以大概就是遍历这个数组,如果nums[i]的值应该hash到的index上的值(也就是nums[nums[i] - 1])不等于nums[i],那就交换这两个数字。如果这个值<= 0或者>= len那就不需要考虑它们。(为什么不考虑 == len呢,其实考虑也行但是没必要?因为最后我们anyways都会return len + 1?这个待定......)

那么这里又有一个tricky point,就是如果单纯的swap的话,会出现一种情况,把小的数字从后面swap到前面,然后就被skip了,就不会被放到正确的位置上了。举个例子就是[-1,4,2,1,9,10],第一次swap 4和1,变成[-1,1,2,4,9,10],然后下一次swap 2和1,变成[-1,2,1,4,9,10],最后这个1一直没被放在正确的位置上就return 1了......于是又去研究了和答案的不同,发现可以通过在每次循环结束后再把i--,就可以再判断一次这个位置上的数字在不在正确的位置上,妙啊。但是这样的话需要在continue的那个if里面加上判断如果当前已经是正确位置了就不需要再swap了,不然就死循环了。

第一次successful submission

class Solution {
    public int firstMissingPositive(int[] nums) {
        // 0 1 2 3 4
        // 1 2 3 x 5
        int len = nums.length;
        for (int i = 0; i < len; i++) {
            if (nums[i] <= 0 || nums[i] >= len || nums[nums[i] - 1] == nums[i]) {
                continue;
            }
            swap(nums, nums[i] - 1, i);
            i--;
        }
        for (int i = 0; i < len; i++) {
            if (nums[i] != i + 1) {
                return i + 1;
            }
        }
        return len + 1;
    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

还有一种最popular的nested loop的方法,着实是不想看啊,太复杂了,for里面套个while。但是somehow看到一种easy to understand的方法,哦其实也跟上面这个差不多,把第一个for改成while,不swap的时候才++,本质是一样的,但是感觉这样确实没有i--这么tricky:https://leetcode.com/problems/first-missing-positive/solutions/17071/my-short-c-solution-o-1-space-and-o-n-time/comments/147659

以及这种思想好像叫做cyclic sort:https://leetcode.com/problems/first-missing-positive/solutions/17214/java-simple-solution-with-documentation/comments/1255253 着实是不想看了......

相关推荐
虽千万人 吾往矣1 小时前
golang LeetCode 热题 100(动态规划)-更新中
算法·leetcode·动态规划
姚先生974 小时前
LeetCode 209. 长度最小的子数组 (C++实现)
c++·算法·leetcode
HUT_Tyne2655 小时前
力扣--LCR 53.最大数组和
算法·leetcode·动态规划
南宫生5 小时前
力扣-数据结构-1【算法学习day.72】
java·数据结构·学习·算法·leetcode
chenziang15 小时前
leetcode hot100 删除链表的第n个节点
算法·leetcode·链表
清炒孔心菜6 小时前
每日一题 342. 4的幂
leetcode
刚学HTML8 小时前
leetcode 05 回文字符串
算法·leetcode
冠位观测者8 小时前
【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序
数据结构·算法·leetcode
古希腊掌管学习的神9 小时前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
DARLING Zero two♡11 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode