Day24 缺失的第一个正数

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

https://leetcode-cn.com/problems/first-missing-positive/

进阶:你可以实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案吗?

示例1:

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

示例2:

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

示例3:

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

提示:

0 <= nums.length <= 300
-231 <= nums[i] <= 231 - 1

Java解法

思路:

  • 找没有出现的最小值+未排序–> 将数据按序
  • 新建对应数组,下标位置存储对应数据存储index出现个数
  • 为0表示该数据没有出现,抛出,全都出现,表示长度值
  • 存储用了nums长度(不知道是否符合进阶要求,查看下官方解)
package sj.shimmer.algorithm.ten_3;

/**
 * Created by SJ on 2021/2/17.
 */

class D24 {
    public static void main(String[] args) {
        System.out.println(firstMissingPositive(new int[]{1,2,0}));
        System.out.println(firstMissingPositive(new int[]{3,4,-1,1}));
        System.out.println(firstMissingPositive(new int[]{7,8,9,11,12}));
        System.out.println(firstMissingPositive(new int[]{1}));
    }
    public static int firstMissingPositive(int[] nums) {
        if (nums == null||nums.length==0) {
            return 1;
        }
        int[] n = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            int num = nums[i]-1;//-1表示位置进行前移一位,0不为正数
            if (num>nums.length-1||num<0) {
                continue;
            }
            n[num] = ++n[num];
        }
        for (int i = 0; i < n.length; i++) {
            if (n[i]==0) {
                return i+1;
            }
        }
        return n.length+1;
    }
}

官方解

https://leetcode-cn.com/problems/first-missing-positive/solution/que-shi-de-di-yi-ge-zheng-shu-by-leetcode-solution/

角度算法都可以,但效率都没有特别好。。。

  1. 哈希表

    原文可以进链接,这里表述下我的理解

    1. 将所有负数置为长度+1(范围外),将所有数据变为正数

    2. 对所有在范围内的数据打上标记(将该数据的值减一的下标值进行添加-号,不用重复加)

    3. 遍历数据的时候发现有负数说明下一个数据是经历过标记的

    4. 相比较而言,内存上减少了一般,但依然是常数级的,两个循环可以优化为一个,个人之前考虑过在同一数组上处理,但没找到合适的标记方式,官方解这个角度NICE

      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 + 1;
                  }
              }
              for (int i = 0; i < n; ++i) {
                  int num = Math.abs(nums[i]);
                  if (num <= n) {
                      nums[num - 1] = -Math.abs(nums[num - 1]);
                  }
              }
              for (int i = 0; i < n; ++i) {
                  if (nums[i] > 0) {
                      return i + 1;
                  }
              }
              return n + 1;
          }
      }
      

    • 时间复杂度:O(N)
    • 空间复杂度:O(1)
  2. 置换

    这个应该是我想到但没做到的想法(主要是想一次循环完成),将数据归位

    [3, 4, -1, 1] 恢复为:[1, -1, 3, 4]

    官方解是每次循环交换一个正确的数据

    class Solution {
        public int firstMissingPositive(int[] nums) {
            int n = nums.length;
            for (int i = 0; i < n; ++i) {
                while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
                    int temp = nums[nums[i] - 1];
                    nums[nums[i] - 1] = nums[i];
                    nums[i] = temp;
                }
            }
            for (int i = 0; i < n; ++i) {
                if (nums[i] != i + 1) {
                    return i + 1;
                }
            }
            return n + 1;
        }
    }
    

    • 时间复杂度:O(N)
    • 空间复杂度:O(1)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值