*PAT_甲级_1067 Sort with Swap(0, i) (25point(s)) (C++)【贪心算法】

目录

1,题目描述

题目大意

2,思路

数据结构

算法

3,AC代码

4,解题过程

第一搏

第二搏

第二搏


1,题目描述

Sample Input:

10
3 5 7 2 6 4 9 0 8 1

 

Sample Output:

9

题目大意

对给出的一系列数字(从0到N-1),不断地将0与其他数字交换,直至数列递增有序。输出至少交换的次数。 

 

2,思路

数据结构

  • int index[N]:下标为元素,值为元素所在位置;(eg.index[0]=12,表示0在位置12处)

算法

  1. 设计for循环,遍历从1到N-1的每一个数,看是否在正确的位置上(index[i] == i);
  2. 若不在,说明尚未排好序。设计while循环,不断将0与0对应的值进行交换 (swap(index[0],index[index[0]])),每次互换可以确定一个正确位置,直到0回到了位置0(或者是序列有序,0最后才回到正确位置)。如下图第五行所示,此时判断i是否在正确位置(index[i] == i),若不是,则将0与位置i对应元素互换,此次互换不能将一个元素放在正确位置上,但可以保证循环继续进行

 

 

3,AC代码

#include<bits/stdc++.h>
using namespace std;

int main(){
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE

    int N, num, cnt = 0;
    cin>>N;
    int index[N];
    for(int i = 0; i < N; i++){
        scanf("%d", &num);
        index[num] = i;
    }

    for(int i = 1; i < N; i++){
        if(index[i] != i){
            while(index[0] != 0){
                swap(index[0], index[index[0]]);
                cnt++;
            }
            //跳出循环可能是已经排好序 或是0回到了位置0
            if(index[i] != i){              //未排好序
                swap(index[0], index[i]);   //将i所在的位置换到下标0对应的位置 下一次即可将i跳到正确位置上
                cnt++;
            }
        }
    }
    cout<<cnt;
    return 0;
}

 

4,解题过程

第一搏

一开始没看清题目(只能元素0与其他元素交换),还一直纳闷,最少不是7步吗?

搜索了其他大神的解法后,才发现,题意没理解对。。。(审题很重要!!!

第二搏

声明了两个数组,一个data存放原先顺序的数字,另一个index存放每个元素对应的下标(即下标对数字,数字对下标);

不断地将0下标对应的数字,与0交换,并更新index数组;

若0下标对应数字为0,且数组尚未排好序,则随机与一个未确定位置的元素交换(图中红色部分,第一次是0与9交换,第二次是0与1交换,最终的步数都一样)

#include<bits/stdc++.h>
using namespace std;

int N;
int findNext(int index[]){
    for(int i = 0; i < N; i++){
        if(index[i] != i)
            return i;
    }
    return -1;
}
int main(){
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE

	cin>>N;

	int data[N], index[N];//data原始数据 index数据对应的下标
	for(int i = 0; i < N; i++){
        scanf("%d", &data[i]);
        index[data[i]] = i;
	}

    int pos, p, num = 0;//pos第一个
    pos = findNext(index);
    while(pos != -1){
        if(index[0] == 0){
            swap(data[0], data[index[pos]]);
            swap(index[0], index[pos]);
            num++;
        }
        while(index[0] != 0){
            p = index[0];
            swap(data[p], data[index[p]]);
            swap(index[0], index[p]);
            num++;
        }
        pos = findNext(index);
    }

    cout<<num;
    return 0;
}

第二搏

欣赏了柳神的做法后(膜!),发现我的做法主要有几点比较耗时:

  1. 维护了两个数组,一个数组存放原始数列data(下标为应该的顺序,值为当前位置元素,不断更新,直到每个元素都在对应位置),另一个存放元素对应的位置index(下标对应元素,值为元素在data中的位置);【实际上只需要一个index数组即可】
  2. 使用findNex(逐个遍历数组,看元素是否在其对应位置上)来循环判断算法是否结束;【只需要一个循环从1到N-1即可,若当前元素在正确位置,则跳过,否则不断地将0与其下标对应的元素互换位置。】

单走一个6! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值