题目描述
// 41. 缺失的第一个正数
// 给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
// 进阶:你可以实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案吗?
题解
// 暴力排序法
// 排序,定义结果保存位res=1,从头往尾遍历元素nums[i],如果元素等于res,
// res累加1。
// 执行用时:4 ms, 在所有 Java 提交中击败了6.63%的用户
// 内存消耗:84.6 MB, 在所有 Java 提交中击败了5.00%的用户
class Solution {
public int firstMissingPositive(int[] nums) {
Arrays.sort(nums);
int res = 1;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == res) {
res++;
}
}
return res;
}
}
// 计数排序法
// 由于要找正数,正数从1开始数起,我们希望像计数排序那样index对应的元素
// 设置为相同的元素,比如索引0对应元素0,索引1对应元素1。但是元素只从1开始
// 所以只好索引0元素1,索引1对应元素2,有:
// 索引: 0 1 2 3 4 ...
// 数组:[1,2,3,4,5...]
//
// 所以索引i对应元素nums[i] - 1,或者说nums[i]元素应该对应索引i+1。
// 如果我们有nums[i]元素,那nums[i]元素本来应该在的位置索引应为nums[nums[i]-1]
// (【索引i对应元素nums[i] - 1]】规则下,两边加上nums[]就有:【元素nums[i]
// 对应位置nums[nums[i] - 1])
// 所以如果当前元素nums[i]和索引i不满足对应关系。那nums[i]本来应该在的位置
// 为nums[nums[i] - 1]。
//
// 知道了这点之后我们for循环遍历数组,遍历元素为nums[i],在保证数组不越界
// 前提下,如果i与nums[i] - 1不相等,且nums[i]与nums[nums[i] - 1]不相等
// 则相应索引上的元素不对,while循环交换i和nums[i]-1的元素。
// 遍历完之后,第二个for循环,逐个遍历nums数组元素nums[i] 判断是否i
// 与nums[i] - 1相等,如果不相等,说明对应元素正数缺失,直接返回该正数
// i+1。否则说明nums给的正数都是连续的,没有中间正数缺失的情况,则缺失的
// 正数就是nums出现的连续正数的下一个正数,即nums.length + 1
//
// 执行用时:1 ms, 在所有 Java 提交中击败了72.97%的用户
// 内存消耗:84 MB, 在所有 Java 提交中击败了5.64%的用户
class Solution {
public int firstMissingPositive(int[] nums) {
int len = nums.length;
for (int i = 0; i < len; i++) {
while (nums[i] >= 1 && nums[i] <= len && i != nums[i] - 1 && nums[i] != nums[nums[i] - 1]) {
swap(nums, i, nums[i] - 1);
}
}
for (int i = 0; i < len; i++) {
if (i != nums[i] - 1)
return i + 1;
}
return nums.length + 1;
}
public void swap(int[] nums, int i, int j) {
if (i != j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}