[leetcode] First Missing Positive

本文探讨了在未排序整数数组中寻找最小缺失正整数的问题,提出了两种解决方案:一是使用列表保存元素并逐个检查,二是采用类似于计数排序的方法,利用数组自身进行优化,实现O(n)时间复杂度和常量空间复杂度。

Given an unsorted integer array, find the smallest missing positive integer.

Example 1:

Input: [1,2,0]
Output: 3

Example 2:

Input: [3,4,-1,1]
Output: 2

Example 3:

Input: [7,8,9,11,12]
Output: 1

Note:

Your algorithm should run in O(n) time and uses constant extra space.


分析:题目意思很明确,要求找数组中没有出现的最小的正整数。

一个最原始的思路,就是从1开始递增,挨个判断是否在数组中。因此需要用一个list保存一下原数组元素,才能用contains方法。

 1 class Solution {
 2     public int firstMissingPositive(int[] nums) {
 3         List<Integer> list = new ArrayList<>();
 4         for ( int n:nums )  
 5             list.add(n);
 6         for ( int i = 1 ; ; i ++ ){
 7             if (!list.contains(i) ) return i;
 8         }
 9     }
10 }

    运行时间7ms,但是这种方法,时间复杂度是O(n),空间复杂度是O(n)。不符合要求。

第二个思路:参考了网上大神的代码,毕竟是hard,求解太巧妙了。

这道题要求用线性时间和常量空间,思想借鉴到了Counting sort中的方法,参见Counting sort - Wikipedia。既然不能用额外空间,那就只有利用数组本身,跟Counting sort一样,利用数组的index来作为数字本身的索引,把正数按照递增顺序依次放到数组中。即让A[0]=1, A[1]=2, A[2]=3, ... , 这样一来,最后如果哪个数组元素违反了A[i]=i+1即说明i+1就是我们要求的第一个缺失的正数。对于那些不在范围内的数字,我们可以直接跳过,比如说负数,0,或者超过数组长度的正数,这些都不会是我们的答案。

代码如下:

 

 1 class Solution {
 2     public int firstMissingPositive(int[] nums) {
 3         //把所有数字放回对应的index;
 4         int start = 0;
 5         while(start < nums.length) {
 6             if(nums[start] <= 0 || nums[start] == start + 1 || nums[start] > nums.length) {
 7                 start++;
 8             } else if(nums[nums[start] - 1] != nums[start]){
 9                 swap(nums, start, nums[start] - 1);
10             } else {
11                 start++;
12             }
13         }
14         start = 0;
15         while(start < nums.length) {
16             if(nums[start] == start + 1) {
17                 start++;
18             } else {
19                 break;
20             }
21         }
22         return start + 1;
23     }
24     private void swap(int[] nums, int l, int r) {
25         int tmp = nums[l];
26         nums[l] = nums[r];
27         nums[r] = tmp;
28     }
29 } 

 

转载于:https://www.cnblogs.com/boris1221/p/9718334.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值