• 【LeetCode】缺失的第一个正数 [H](双指针)


    41. 缺失的第一个正数 - 力扣(LeetCode)

    一、题目

    给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

    请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

    示例 1:

    输入:nums = [1,2,0]
    输出:3

    示例 2:

    输入:nums = [3,4,-1,1]
    输出:2

    示例 3:​​​​​​​

    输入:nums = [7,8,9,11,12]
    输出:1

    提示:

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

    二、代码

    1. class Solution {
    2. public int firstMissingPositive(int[] nums) {
    3. // 过滤无效参数
    4. if (nums == null || nums.length == 0) {
    5. return 1;
    6. }
    7. // l左边都是有效区的数。有效区的所有书都满足nums[i] = i + 1
    8. int l = 0;
    9. // r及其r右边的数都是垃圾区。永远不可能加入到有效区的数,就加入垃圾区
    10. int r = nums.length;
    11. while (l != r) {
    12. // 1、如果l位置的数等于l+1,说明这个数是有效区的数,加入有效区
    13. if (nums[l] == l + 1) {
    14. // 有效区右扩
    15. l++;
    16. // 2、如果l位置的数已经存在在有效区了(nums[l] <= l) 或者 l位置的数大于r 或者在nums[l] - 1已经存在符合有效区规则的nums[l]了,就将l位置的数加入到垃圾区
    17. } else if (nums[l] <= l || nums[l] > r || nums[nums[l] - 1] == nums[l]) {
    18. // 将l交换到垃圾区,并且将垃圾区左扩
    19. swap(nums, l, --r);
    20. // 如果nums[nums[l] - 1] != nums[l],就将l和nums[l] - 1位置的数交换
    21. } else {
    22. swap(nums, l, nums[l] - 1);
    23. }
    24. }
    25. // r+1就是缺少的最小的正数
    26. return r + 1;
    27. }
    28. public void swap(int[] nums, int i, int j) {
    29. int temp = nums[i];
    30. nums[i] = nums[j];
    31. nums[j] = temp;
    32. }
    33. }

    三、解题思路 

    假设L来到下标17位置,说明0~16位置属于有效区,有效区内已经存好了1....17依次增加的正整数,那么此时L位置的数,什么情况下才是要被放到垃圾区呢?

    1) L位置的数 <= L,说明这个数已经存在于有效区了,要将其放到垃圾区,已经收集过的数字会让最好情况变差,因为会占用空间。

    2)如果L位置的数 > R,那么它也是垃圾区的数,因为大小超过R,前面一定有不存在的更小的正整数。很好理解,假设有5个位置,然后放1~10大小的数,其中的数肯定有断层的时候,这个断层中就有最小的没出现过的正整数。

    3)假设此时R在31位置,L在17位置。如果L位置上的数是23,我们不能确定他是不是垃圾,因为它小于等于R,后面可能成为有效区的数。这个时候23如果是有效区的数,那么他就应该放在下标22位置,所以将他和下标22位置的数交换:

    1. 如果此时发现下标22位置的数已经有23了,那么L位置的23就是重复了,直接和R-1位置交换,R--,将其加入垃圾区。
    2. 如果下标22位置的数不是23,就L位置和下标22位置的数交换,然后再用相同的流程去判断此时L交换过来的数符合那种情况。

    4)如果此时L位置的数等于L+1,那么这个数就是有效区的,将L右移,将其加入有效区。

  • 相关阅读:
    Mysql 45讲学习笔记(二十四)MYSQL主从一致
    python中使用sqlalchemy操作数据库遇到密码包含@的处理方法
    Go语法之函数 defer使用
    基于Splinter演示如何使用Chrome WebDriver
    Kafka3.0.0版本——消费者(消费者组初始化流程图解)
    environment.yaml或者requirements.txt
    学习MySQL的第一天:MySQL概述(基础篇)
    小米面试——案例总结
    40 道基础Dubbo 面试题及答案
    Unity快手上手【熟悉unity编辑器,C#脚本控制组件一些属性之类的】
  • 原文地址:https://blog.csdn.net/cy973071263/article/details/127688316