PAT A1067 Sort with Swap(0, i)

PAT A1067 Sort with Swap(0, i)

在这里插入图片描述

Sample Input:

10
3 5 7 2 6 4 9 0 8 1

Sample Output:

9
wordmeaning
permutation sequence排列顺序
  • 分析:
    要求只用swap(0, x),完成排序,且步数最少
    刚一看,很蒙蔽,慢慢就发现了一个条件(这些数从0开始不间断),这个条件很重要!!
    要想交换步数最少,根据贪心的原则,每次和0交换的元素都最优的选择,如果每次0都和他的下标的元素交换,就可以把下标元素排到最终位置,保证了每一步都是最优的选择
    -》这时产生的问题有:
    问题1.如何找到下标?
    问题2.如果0交换到了0位置,而其他元素未完全有序怎么办?

  • 思路 1:
    -》对应的解决方案:
    问题1.使用一个下标数组Idex[]记录每个元素的下标,并且随着交换而同步更新
    问题2.设一个变量right表示,左边已经排好序的序列的末尾(也就是从左往右第一个还没就位的位置),这样如果0换到0位置,下一次让他和right位置的元素交换,从而使循环能进行下去
    由解决方案2很自然的想到 while 的退出条件就是right<n

  • code 1:

#include <stdio.h>
#include <algorithm>	//swap函数 
using namespace std;
const int maxn = 100010;
int num[maxn], idex[maxn];

int main(){
	int n;
	scanf("%d", &n);
	for(int i = 0; i < n; ++i){
		scanf("%d", &num[i]);
		idex[num[i]] = i;	//存储数字的所在的下标 
	}
	int cnt = 0, right = 1;	//right:最靠前的已经排好序的子序列的末位 
	while(right < n){
		if(num[0] == 0){
			swap(idex[num[right]], idex[0]);	//!!!Wrong 1: 要先更新索引数组,否则num[right]先被交换了,出错 
			swap(num[0], num[right]);
		}else{
			int aim = idex[0];
			swap(num[idex[0]], num[idex[aim]]);
			swap(idex[aim], idex[0]);	//更新索引数组 
			while(num[right] == right) right++;	 
		}
		cnt++;
	}
	printf("%d", cnt);
	return 0;
}
  • T3 code:
#include <bits/stdc++.h>
using namespace std;
vector<int> seq, pos;
void FindFirst(int & up){ while(pos[up] == up) up++; }
int main()
{
    int n;
    scanf("%d", &n);
    seq.resize(n); pos.resize(n);
    for(int i = 0; i < n; ++i)
    {
        scanf("%d", &seq[i]);
        pos[seq[i]] = i;
    }
    int step = 0, upper = 0;
    while(upper < n)
    {
        int pos0 = pos[0], pos_nex = pos[pos[0]];
        if(pos[0] == 0)
        {
            FindFirst(upper);
            pos_nex = upper;
        }
        if(upper < n)
		{
			swap(pos[0], pos[seq[pos_nex]]);
        	swap(seq[pos0], seq[pos_nex]);
        	step++;        	
		}else printf("%d", step);
    }
   	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值