【双指针】缺失的第一个正整数
改一下输入输出格式,第一行输入n,接下来输入n个整数,输出缺失的第一个正整数。这道题需要分情况讨论,用左程云老师的例子来举例,现在n=10,10个整数依次为-3,2,1,8,5,4,2,3,5,13,假设它们存储在数组a中,下标从1开始。我们定义两个变量l和r,l表示前l个(包括l)是已经顺好的(即下标1存放1,下标2存放2,下标3存放3,依此类推),从第r个位置开始存储不符合要求的整数,不符合要求的整数满足一下其中一个条件:
1)a[l]<l;(比如例子中的-3) 2) a[l]>r; (比如例子中的13)
3)a[a[l]]==a[l] (有重复的数)。
整体算法的流程是:初始化l=1,r=n+1,一开始假设全部都是顺好的。接着按以下情况去判断和操作:
情况 | 操作 | 说明 |
---|---|---|
a[l]==l | l=l+1 | 当前的顺好了,就继续看下一个是否顺好 |
a[l]<l | r=r-1, swap(a[l],a[r]) | 把不符合要求的移到r右边,缩小符合要求的范围 |
a[l]>r | r=r-1, swap(a[l],a[r]) | 把不符合要求的移到r右边,缩小符合要求的范围 |
a[a[l]]==a[l] | r=r-1, swap(a[l],a[r]) | 把不符合要求的移到r右边,缩小符合要求的范围 |
除了以上四种情况的其他情况 | swap(a[l],a[a[l]]) | 把当前元素交换到它应该在的位置 |
代码实现:
#include<bits/stdc++.h>
using namespace std;
int n,l,r,a[100005];
int main(){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];l=1; r=n+1;while(l<=r){if(a[l]==l) l++;else if(a[l]>r||a[l]<l||a[a[l]]==a[l]){r--;swap(a[l],a[r]);} else swap(a[l],a[a[l]]); }cout<<r+1<<endl;