点击蓝色“
五分钟学算法
”关注我哟
加个“
星标
”,天天中午 12:15,一起学算法
来源 | 五分钟学算法
今天分享的题目来源于 LeetCode 第 41 号问题:缺失的第一个正数。
题目描述
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
示例 1:
输入: [1,2,0]
输出: 3
示例 2:
输入: [3,4,-1,1]
输出: 2
示例 3:
输入: [7,8,9,11,12]
输出: 1
说明:
你的算法的时间复杂度应为O(
n
),并且只能使用常数级别的空间。
题目解析
这道题使用桶排序的思路,即 “一个萝卜一个坑”,就可以解决。可以就使用题目中的例子,在纸上写写画画,就能得出思路,只不过在编码上需要注意一些细节。
我们可以把数组进行一次“排序”,“排序”的规则是:
如果这个数字 i 落在“区间范围里”,i 就应该放在索引为 i - 1 的位置上
,下面具体解释。
1、数字
i
落在“区间范围里”;
例如:
[3, 4, -1, 1]
,一共 4 个数字,那么如果这个数组中出现 “1”、“2”、“3”、“4”,就是我们重点要关注的数字了;
又例如:
[7, 8, 9, 11, 12]
一共 5 个数字,每一个都不是 “1”、“2”、“3”、“4”、“5” 中的一个,因此我们无须关注它们;
2、
i
就应该放在索引为
i - 1
的位置上;
这句话也可以这么说 “
索引为 i 的位置上应该存放的数字是 i + 1
”。
就看上面那张图,数字 1 应该放在索引为 0 的位置上,数字 3 应该放在索引为 2 的位置上,数字 4 应该放在索引为 3 的位置上。一个数字放在它应该放的位置上,我们就认为这个位置是“和谐”的,看起来“顺眼”的。
按照以上规则排好序以后,缺失的第 1 个正数一下子就看出来了,那么“最不和谐”的数字的索引 +1,就为所求。
那如果所有的数字都不“和谐”,数组的长度 +1 就为所求。
动画描述
图片描述
以下是上面 gif 图的静态图。
LeetCode 第 41 题:缺失的第一个正数-1
LeetCode 第 41 题:缺失的第一个正数-2
LeetCode 第 41 题:缺失的第一个正数-3
LeetCode 第 41 题:缺失的第一个正数-4
LeetCode 第 41 题:缺失的第一个正数-5
LeetCode 第 41 题:缺失的第一个正数-6
LeetCode 第 41 题:缺失的第一个正数-7
LeetCode 第 41 题:缺失的第一个正数-8
代码实现
public class Solution {
public int firstMissingPositive(int[] nums) {
int len = nums.length;
for (int i = 0; i
while (nums[i] > 0 && nums[i] <= len && nums[nums[i] - 1] != nums[i]) {
swap(nums, nums[i] - 1, i);
}
}
for (int i = 0; i
if (nums[i] - 1 != i) {
return i + 1