问题描述:
Given an unsorted integer array, find the first missing positive integer.
For example,
Given [1,2,0]
return 3
,
and [3,4,-1,1]
return 2
.
Your algorithm should run in O(n) time and uses constant space.
原问题链接:https://leetcode.com/problems/first-missing-positive/
问题分析
这个问题粗看起来几乎没有什么好的办法可以解决。因为这里是对应着一个数组,它里面的元素的值可以为正也可以为负,同时有的值还可能出现多次。而且这个问题里比较苛刻的地方就是要求运行时间为O(n) 而且只能使用常量的空间。所以也不能额外申请别的数据结构来存储数据。
似乎没什么办法可以解决。不过问题里有一个细节可以起到一定的效果。就是要判断它的首个缺失的正整数时,它是从数字1开始往后的。那就是说如果这个数组里如果没有1,那么假设最终将它里面的负数部分挪走而且排序之后,那么它将不会是以1开头。也就是说它缺失的就是数字1。所以说,如果我们能够达到这么一个效果,就是将所有的正数都按照排序的结果调整到数组里,而且和它们所在的索引位置一致就好了。比如说下标为1的数组元素a[1] = 3。那么它将会被放到数组里第3个位置的地方,也就是索引为2的地方。
要能够对元素这么调整得到一个排序的效果同时其时间复杂度为O(n)的方法。从这个角度来看选择不多。一个典型的方法就是counting sort。在这里能不能用上这种方法的思路呢?
在实际counting sort的方法里,因为要对元素的个数进行计数,额外使用了一个数组。而且那里是假设所有的元素取值都在数组长度的范围内。所以这里不能直接照搬过来。但是我们也有了这么一个思路。就是如果我们碰到数组里某个元素的时候,假设为a[i]。我们可以根据a[i]的值来处理。假设a[i] >= 1 && a[i] <= n (n为数组长度)。这个时候,表示这个值可以映射到数组里。我们可以将它放到它在理想排序后情况下的位置。也就是a[a[i] - 1]这个地方。因为我们这里取的所有值都是从1到n,而实际数组的索引是从0开始,所以这里要减一。嗯,这样的一个调整可以实现将一个元素调整到它理想的位置。但是这里要将所有符合条件的元素都调整到它理想的地方,光直接这么交换能行吗?
比如说有数组[3, 4, 2, -1]。如果我们每次碰到一个在合法范围内的值就光做一个交换的话,它每次变化的情况如下:
[2, 4, 3, -1], [2, -1, 3, 4]。最终因为一些位置的交换我们将漏过一些元素。所以,当我们将a[i]和a[a[i] - 1]的位置调整后还应该看现在a[i]这个位置的值的情况。所以我们应该用一个循环来调整这些值。这里的循环有几个条件,一个是要保证当前a[i]的值在[1, n]区间内。所以有a[i] >= 1 && a[i] <= n。另外,这个循环要终止必然要使得a[i] == i + 1的情况。在这种情况下它其实已经在它所需要放的位置了。还有一种情况就是当a[i] == a[a[i] - 1]。就是它和它所要交换的元素值是相同的。这是对应有出现重复的元素的情况。这样我们就得到一个合理的调整步骤了。
剩下的事情就是来判断这个缺失的正整数了。我们需要遍历一次这个数组,并且判断a[i] == i + 1这个情况。如果相同,则继续下一个,否则i + 1就是缺失的值。还有一种情况是如果循环结束了还没有碰到上述条件的,那就说明这个数字数组长度加1。
最终实现的代码如下:
public class Solution { public int firstMissingPositive(int[] a) { if (a == null || a.length == 0) { return 1; } int n = a.length; for (int i = 0; i < n; i++) { while (a[i] >= 1 && a[i] <= n && a[i] != i + 1 && a[i] != a[a[i] - 1]) { int j = a[i] - 1; swap(a, i, j); } } for (int i = 0; i < n; i++) { if (a[i] != i + 1) { return i + 1; } } return n + 1; } public void swap(int[] a, int i, int j) { int temp = a[i]; a[i] = a[j]; a[j] = temp; } }
总结
这个问题难在对各种细节的处理。很容易因为一种情况而忽略了其他的条件。能够用简短的代码来描述这些步骤还是值得仔细推敲的。
相关推荐
java java_leetcode题解之First Missing Positive.java
leetcode 71 Python用 ...Missing Positive (HARD) leetcode 42. 收集雨水 (HARD) leetcode 44. 通配符匹配 (HARD) leetcode 45. Jump Game II (HARD) Leetcode 51. N-Queens (HARD) Leetcode 52. N-
leetcode打不开Leetcode Note Tips Tip1: Two pointer for sorted array (#Array 1. Two Sum) Tip2: Sum[i:j] = Sum[0:j] - Sum[0:i] for continuous array (# Array 560. Subarray Sum Equals K) Tip3: Knapsack ...
First Missing Positive 广度优先搜索 773. Sliding Puzzle 864. Shortest Path to Get All Keys 深度优先搜索 996. Number of Squareful Arrays 拓扑排序 269. Alien Dictionary 单调栈 42. Trapping Rain Water 85...
题:**First Missing Positive 给定一个未排序的整数数组,找到第一个缺失的正整数。 例如,给定 [1,2,0] 返回 3,而 [3,4,-1,1] 返回 2。 您的算法应该在 O(n) 时间内运行并使用恒定空间。 **第 0003 题:**String ...
缺失的第一个整数](./Array/first-missing-positive.md) [0042 接雨水](./Array/trapping-rain-water.md) [0048 旋转图像](./Array/rotate-image.md) Heap 堆 [0023 合并K个排序链表](./Heap/merge-k-sorted-lists....
c语言入门 C语言_leetcode题解之41-first-missing-positive.c
js js_leetcode题解之41-first-missing-positive.js
├── First Missing Positive │ ├── Readme.md │ └── solution.js ├── Trapping Rain Water │ ├── Readme.md │ └── solution.js ├── Wildcard Matching │ ├── Readme.md │ └── ...
268| [Missing Number](https://leetcode.com/problems/missing-number/) | [C++](./C++/missing-number.cpp) [Python](./Python/missing-number.py) | _O(n)_ | _O(1)_ | Medium | LintCode || 318| [Maximum ...
41_First_Missing_Positive 299_Bulls_and_Cows 134_Gas_Station 118_Pascal's_Triangle_I 119_Pascal's_Triangle_II 169_Majority_Element 229_Majority_Element_II 274_H_索引 275_H_Index_II 217_Contain_...
- First Missing Positive: 找出数组中缺失的最小正数。 - Trapping Rain Water: 给定一个数组,其中每个元素代表一个宽度为1的柱子高度,计算能接多少雨水。 - Multiply Strings: 给定两个非负整数字符串形式的数,...
2. **First Missing Positive**:这是一个关于数组处理的问题,要求找到数组中第一个缺失的正整数。它需要理解数组的特性并进行有效的遍历,可能使用到排序或哈希表等数据结构。 3. **Best Time to Buy and Sell ...
- First Missing Positive(缺失的第一个正数) - 2 Sum(两数之和) - 3 Sum(三数之和) - 3 Sum Closest(三数之和最接近) - Remove Duplicates from Sorted Array(删除有序数组中的重复项) - Remove ...
- **数组中的第一个不重复的数字(First Missing Positive)**: 找出数组中缺失的第一个正数。 #### 排序算法 - **合并排序数组(Merge Sorted Array)**: 将两个排序数组合并成一个新的排序数组。 - **寻找数组中的中...
本资源包聚焦于LeetCode的第41题——"缺失的第一个正数"(First Missing Positive)。这是一道中等难度的题目,旨在检验程序员对数组处理以及优化算法的能力。下面将详细探讨这个问题的解决方案、相关的C++编程技巧...
"First Missing Positive"是LeetCode中的一道经典问题,旨在考察我们对数组操作的理解以及对算法设计的能力。这个问题的标题是"第一个缺失的正数",其核心目标是从给定的未排序整数数组中找到最小的缺失正整数。 ...
leetcode 2 code_interview leetcode和lintcode的一些题目的解法 是剑指offer 是面试中遇到的有意思的题目总结,比如说BAT,intel,NVIDIA等公司面试的题目记录 ...41-first-missing-positive 01-Two-Sum 求解第K
股票买卖最佳时机leetcode Java项目 这是 ...First_Missing_Positive Generate_All_Parenthesis_2 实现_StrStr Largest_Distance_Between_Nodes_Of_A_Tree Largest_Rectangle_In_Histogram Least_C
收集面试中提出的一些重要问题。...//leetcode.com/problems/maximum-subarray/ https://leetcode.com/problems/first -missing-positive / https://leetcode.com/problems/container-with-most-water/ htt