【PAT】【Advanced Level】1067. Sort with Swap(0,*) (25)

本文探讨了一种特殊的排序问题,仅允许使用Swap(0,*)操作来对0到N-1的排列进行排序。通过构建环形结构的方法,实现了对任意排列的最小交换次数求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1067. Sort with Swap(0,*) (25)

时间限制
150 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Given any permutation of the numbers {0, 1, 2,..., N-1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:

Swap(0, 1) => {4, 1, 2, 0, 3}
Swap(0, 3) => {4, 1, 2, 3, 0}
Swap(0, 4) => {0, 1, 2, 3, 4}

Now you are asked to find the minimum number of swaps need to sort the given permutation of the first N nonnegative integers.

Input Specification:

Each input file contains one test case, which gives a positive N (<=105) followed by a permutation sequence of {0, 1, ..., N-1}. All the numbers in a line are separated by a space.

Output Specification:

For each case, simply print in a line the minimum number of swaps need to sort the given permutation.

Sample Input:
10 3 5 7 2 6 4 9 0 8 1
Sample Output:
9
原题链接:

https://www.patest.cn/contests/pat-a-practise/1067

https://www.nowcoder.com/pat/5/problem/4118

思路:

从任意乱序的位置开始找

如 f(a0)= a1 ,然后  f(a1)= a2,f(a2)= a3。。以此类推可以找到f(a(n-1))= a0,即形成一个环。


如果0 在这个环中,则 

1、设 a0 = 0,f(0)= a1,即 a1 在第0个位置

2、将 a1 放到 合适的位置(即第a1个位置),即 f(a1)处。取出f(a1)的原值,记为 a2

3、将 a2 放到 第 a2 个位置,再将f(a2)的原值取出,记为a3

4、将 a3 放到 第 a3 个位置,以此类推,必有f(a(n-1))=0

5、将 0 放回 第 0 个位置,结束。

以上共有n个元素,共经过了n-1次操作

即,含0的n个元素的环,共移动n-1次。


如果0不在这个环中,则将0加入环中。

令f(0)=a0,f(a(n-1))=0;

则转化成了上述问题

共有n+1个元素,移动n次,在加上0入环的操作,共n+1次。

即,原环n个元素,移动n+1次。

即,不含0的n个元素的环,共移动n+1次。


根据上述规律,对原序列进行搜索,对于搜出的每一个环进行计算。

CODE:

#include<iostream>
#include<cstring>

using namespace std;

int arr[100100];
bool f[100100];

int main()
{
	memset(f,0,sizeof(f));
	int n;
	cin>>n;
	
	for (int i=0;i<n;i++)
	{
		cin>>arr[i];
	}
	int sum=0;
	for (int i=0;i<n;i++)
		if (f[i]==0) 
			if (arr[i]!=i)
			{
				int t=i;
				int ori=arr[i];
				int fl=0;
				while (1)
				{
					//cout<<t<<" "<<arr[t]<<" "<<sum<<endl;
					f[t]=1;
					if (arr[t]==0) fl=1;
					t=arr[t];
					sum++;
					if (arr[t]==ori) break;
				}
				if (fl==1) sum--;
				else
					sum++;
			}	
	cout<<sum;
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值