• 数据结构与算法之排序: Leetcode 41. 缺失的第一个正数 (Typescript版)


    缺失的第一个正数

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

    描述

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

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

    示例 1

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

    示例 2

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

    示例 3

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

    算法实现

    1 )一般思路

    function firstMissingPositive(nums: number[]): number {
      // 过滤掉非正整数
      nums = nums.filter(item => item > 0);
      // 正整数数组是为空
      if (!nums.length) return 1;
      // 升序,目的:方便从左到右取最小值arr[0]
      nums.sort((a, b) => a - b);
      // 如果第一个元素不为1,返回1
      if (nums[0] !== 1) return 1;
      // 从左边开始遍历,只要下一个元素和当前元素差值》1说明当前元素的下一个值(+1)
      for (let i = 0, len = nums.length - 1; i < len; i++) {
        if (nums[i + 1] - nums[i] > 1) {
          return nums[i] + 1;
        }
      }
      // 如果数组是连续的正整数【1,2,3,4,5,6】
      return nums.pop() + 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 这个算法不是最优解,做了很多不需要的事情,比如 filter 和 sort
    • 不需要完全进行排序

    2 )基于冒泡改造

    function firstMissingPositive(nums: number[]): number {
      nums = nums.filter(item => item > 0);
      const n = nums.length;
      let min: number;
      // 实现选择排序,先拿到最小值,如果第一个元素不是1直接返回1,如果是1,就要比相邻元素差值
      for (let i: number = 0; i < n; i++) {
        min = nums[i];
        for (let j: number = i + 1; j < n; j++) {
          if (nums[j] < min) {
            let c = min;
            min = nums[j];
            nums[j] = c;
          }
        }
        nums[i] = min;
        if (i > 0) {
          if (nums[i] - nums[i - 1] > 1) return nums[i - 1] + 1;
        } else {
          if (min !== 1) return 1;
        }
      }
      return nums.length ? nums.pop() + 1 : 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 冒泡排序, 但是会存在 超出时间限制 的问题
    • 或基于其他排序改造均可

    3 )查询表

    function firstMissingPositive(nums: number[]): number {
      const n: number = nums.length;
      const { abs } = Math;
      let i: number;
      for (let i = 0; i < n; ++i) {
          if (nums[i] <= 0) {
              nums[i] = n + 1;
          }
      }
      for (i = 0; i < n; ++i) {
          let num = abs(nums[i]);
          if (num <= n) {
              nums[num - 1] = -abs(nums[num - 1]);
          }
      }
      for (i = 0; i < n; ++i) {
          if (nums[i] > 0) {
              return i + 1;
          }
      }
      return n + 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 官方提供方法
    • 时间复杂度:O(N),其中 N 是数组的长度。
    • 空间复杂度:O(1)。

    4 )置换法

    function firstMissingPositive(nums: number[]): number {
      const n = nums.length;
      let i: number;
      for (i = 0; i < n; ++i) {
          while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
              [nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]]; // 交换
          }
      }
      for (i = 0; i < n; ++i) {
          if (nums[i] != i + 1) {
              return i + 1;
          }
      }
      return n + 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 这是官方提供
    • 时间复杂度:O(N),其中 NNN 是数组的长度。
    • 空间复杂度:O(1)。
  • 相关阅读:
    【一、定制搭建-Arm平台的QT交叉编译环境】
    二十二、环境变量和模式
    Spring Boot 检索&定时任务
    sdfsdfasfsdfdsfasfdfasfasadsfasdfasf
    【python】(一)字符串基本操作
    SpringBoot+Vue项目在线学习网站
    Apache HTTPD (CVE-2017-15715)换行解析漏洞复现
    你以为的Java面试只是背答案?跳槽涨薪不还是得靠自己的技术
    Kafka的数据可靠与数据重复
    一篇文章让你搞懂Java中的静态代理和动态代理
  • 原文地址:https://blog.csdn.net/Tyro_java/article/details/134429994