给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数
进阶:你可以实现时间复杂度为 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;
}
}
image
官方解
角度算法都可以,但效率都没有特别好。。。
哈希表
原文可以进链接,这里表述下我的理解
将所有负数置为长度+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;
}
}
image
时间复杂度: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;
}
}
image
时间复杂度:O(N)
空间复杂度:O(1)