改一下输入输出格式,第一行输入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;