https://leetcode.com/problems/first-missing-positive/
给定一个未排序的数组,找到缺失的最小正整数,要求时间O(n),空间O(1)
一、问题描述
测试用例:
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
要求空间O(1),而且输入数组无序,只能改动数组中元素的分布了
二、代码实现
第一遍遍历将所有正整数元素放在下标为元素值的位置处,第二遍遍历从下标1开始找到第一个nums[i] != i的下标,下标i就是缺失的最小正整数(如果遍历完还没找到,说明缺失的最小正整数为n)。
启示:一般要求O(1)空间的算法只能通过改动原有数据分布来实现;此种方法其实就是桶排序,只不过桶排序中nums[i]存放的是值为i的元素的个数,这里nums[i]存放的是元素值i。
class Solution {
public int firstMissingPositive(int[] nums) {
if (nums == null || nums.length == 0) {
return 1;
}
//1、移动元素到以元素值为下标的位置处,如果该位置已经存在该元素 or 元素小于等于0 or 元素值大于等于n,则不移动
int leftEnd = nums.length; //可能缺失的值
for (int i=0; i<nums.length; ) {
if (nums[i] > 0 && nums[i] < nums.length && nums[nums[i]] != nums[i]) {
swap(nums, i, nums[i]);
} else {
if (nums[i] == nums.length) { //元素值大于等于n 并且 元素值等于n
leftEnd ++; //如果leftEnd出现,则将其加1
}
i++;
}
}
//2、遍历找到第一个不满足nums[i] = i的元素,则i就是缺失的最小正整数
for (int i=1; i<nums.length; i++) {
if (nums[i] != i) {
return i;
}
}
return leftEnd; //如果遍历完所有元素均满足nums[i] = i,则leftEnd为缺失的最小正整数
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
参考:
https://hackernoon.com/14-patterns-to-ace-any-coding-interview-question-c5bb3357f6ed
https://leetcode.com/problems/first-missing-positive/discuss/17298/Sharing-my-2ms-C-solution