leetcode41缺失的第一个正数
要求:给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
时间复杂度:o(n)
空间复杂度:o(1)
很多人觉得这题简单,不应该放在困难区,其实大多数都没有考虑时间复杂度和空间复杂度,其实很多算法题一模一样,只不过对时间复杂度做下要求,难度瞬间提升不少,解决这题需要用到桶排序类似的算法,其实和之前我说select模型的位图差不多是一个概念,这种算法太巧妙了,我刚开始接触的时候真的被惊到了。
例如:3,1,4,5
输出:2
解法:如果我们可以用某种算法将3 1 4 5排成1 5 3 4(即1放在第一个位置,3放在第三个位置,4放在第四个位置,5之能被放在第二个位置了),我们就可以很容易找出缺失的第一个正数是2
下面我们来看看这个算法的运行过程
3,1,4,5
数组长度为4
第一步i=0
a[i]=3, 把3放在第三个位置即i=2的位置,交换3和4
4,1,3,5
只要执行了交换操作,i就不自增
第二步i=0
a[i]=4,把4放在第四个位置即i=3的位置,交换4和5
5,1,3,4
只要执行了交换操作,i就不自增
第三步i=0
5>数组长度4,所以不能把5放在第五个位置,不能交换i++
第四步i=1
5,1,3,4
a[1] =1,把1放在数组第一个位置,即下标为0的位置,5和1交换
1,5,3,4
第五步i=1
a[1]=5,不能交换,i++
第六步i=2
a[2]=3,3已经在合适的位置了,不能交换,i++
第七步i=3
a[3]=4,4已经在合适的位置了,不能交换,i++
public int firstMissingPositive(int[] nums) {
int len = nums.length;
if(null==nums||len==0)return 1;
//数据预处理 桶排序处理数据
for(int i=0;i<len;){
int cur = nums[i];
//满足这四个条件才可以交换
if(cur!=i+1&&cur<=len&&cur>0&&cur!=nums[cur-1]){
//交换 i和cur-1
nums[i] = nums[cur-1];
nums[cur-1] = cur;
}else{
++i;
}
}
//找最小正数
for(int i=0;i<len;++i){
if(i+1!=nums[i]){
return i+1;
}
}
// 1 2 3 4这种情况
return len+1;
}