PAT甲题题解-1067. Sort with Swap(0,*) (25)-贪心算法

贪心算法

次数最少的方法,即:
1.每次都将0与应该放置在0位置的数字交换即可。
2.如果0处在自己位置上,那么随便与一个不处在自己位置上的数交换,重复上一步即可。
拿样例举例:
   0 1 2 3 4 5 6 7 8 9
0:3 5 7 2 6 4 9 0 8 1


1:3 5 0 2 6 4 9 7 8 1
2:3 5 2 0 6 4 9 7 8 1
3:0 5 2 3 6 4 9 7 8 1 (如果0处在自己位置上,那么找一个不在自己位置上的数val与之交换)
4:5 0 2 3 6 4 9 7 8 1
5:5 1 2 3 6 4 9 7 8 0
6:5 1 2 3 6 4 0 7 8 9
7:5 1 2 3 0 4 6 7 8 9
8:5 1 2 3 4 0 6 7 8 9
9:0 1 2 3 4 5 6 7 8 9

在例子第3步交换中,如果每次都线性查找,时间复杂度就会很高,会有2组样例超时。
这里用set优化了下速度。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <vector>
#include <set>
using namespace std;
const int maxn=100000+5;
int a[maxn];
int pos[maxn];
int cnt;
set<int> leftnum; //存储了还没有被放到正确位置上的数字(0除外)
int main()
{
    int n;
    scanf("%d",&n);
    cnt=n; //还未排好序的个数
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        pos[a[i]]=i;
        if(i==a[i])
            cnt--;
        else if(a[i]!=0)
            leftnum.insert(a[i]);
    }
    int p0=pos[0]; //0目前所在的位置
    int p;
    int ans=0;
    while(cnt){
        //将0和应处在0位置的数(p0)交换位置
        a[p0]=p0;
        leftnum.erase(p0);
        p0=pos[p0];
        a[p0]=0;
        ans++;
        cnt--;
        if(p0==0)
            cnt--;
        //如果0在自己位置上,但还没有排好序
        if(p0==0 && cnt){
            //这里用set来优化寻找还没有处在自己位置上的数字,将0与之交换
            int val=*leftnum.begin();
            int tmp=pos[val];
            pos[val]=p0;
            a[p0]=val;
            p0=tmp;
            a[p0]=0;
            ans++;
            cnt++;
        }
    }
    printf("%d",ans);
    return 0;
}
View Code

 

posted @ 2017-03-01 15:32  辰曦~文若  阅读(293)  评论(0编辑  收藏  举报