[leetcode] First Missing Positive

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 } 

 

posted @ 2018-09-28 14:25  Lin.B  阅读(137)  评论(0编辑  收藏  举报