给你一个未排序的整数数组 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;
}
}
官方解
角度算法都可以,但效率都没有特别好。。。
-
哈希表
原文可以进链接,这里表述下我的理解
-
将所有负数置为长度+1(范围外),将所有数据变为正数
-
对所有在范围内的数据打上标记(将该数据的值减一的下标值进行添加-号,不用重复加)
-
遍历数据的时候发现有负数说明下一个数据是经历过标记的
-
相比较而言,内存上减少了一般,但依然是常数级的,两个循环可以优化为一个,个人之前考虑过在同一数组上处理,但没找到合适的标记方式,官方解这个角度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)
-
-
置换
这个应该是我想到但没做到的想法(主要是想一次循环完成),将数据归位
[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)