PTA_2019春_106_Sort with Swap(0, i)

该博客讨论了如何仅通过交换操作(0, i)将任何排列的前N个非负整数按升序排序。它提供了一个例子并说明了如何通过这种操作对特定序列进行排序,并要求找到实现排序所需的最小交换次数。输入输出规格以及示例输入和输出也给出了详细说明。" 38065037,174883,List中Contains、Exists与Any性能比较,"['C#编程', '编程技巧', '性能优化', '.NET框架', '数据结构']
摘要由CSDN通过智能技术生成

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 (≤10​5​​) 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
/*思路:贪心算法,即尽量每次交换使其在其应在的位置
        这题想了好久,一开始的思路是想通过几个例子找出交换的规律,思考的出发点是怎么使序列能有序(这样想不出来)
		想到mooc上那句话,N个数字的排列由若干个独立的环组成,解法由此产生。
		对于0所在的位置,应该放上什么数字,就去找这个数字然后交换,这个操作做下去会形成环,所以当一个环内的
		数字交换完以后,进入下一个环。那么交换的次数可以由环的个数,以及每个环内的元素得到.
		假设遍历一个序列得到N个环,0必在一个环内,
		如果环内只有一个元素,那么不需要交换
		如果多元环且有0,那么只需交换元素个数减一次
		如果多元环没有0,本身交换需要元素个数减一次,还有讲0换进环内,次数加一,0参与进来后,交换又得加一,
		所以一共是元素数量加1*/
#include<stdio.h>
#include<stdlib.h>
int main() {
	int N;
	scanf("%d", &N);
	int* array = (int*)malloc(N * sizeof(int));/*存储输入数据*/
	int* visited = (int*)malloc(N * sizeof(int));/*是否访问过*/
	int* steps = (int*)malloc(N * sizeof(int)); /*每个环的数量,这个数组可以不需要*/
	for (int i = 0; i < N; i++) {
		scanf("%d", &array[i]);
	}
	for (int i = 0; i < N; i++) {
		visited[i] = 0;
	}
	for (int i = 0; i < N; i++) {
		steps[i] = 0;
	}
	/*下面找环*/
	int step, temp;  /*step为环里元素个数*/
	int flag =0;/*标记0在的环*/
	for (int i = 0; i < N; i++) {  /*遍历序列*/
	        temp = i;
		step = 0;
		if (visited[temp] == 1) continue;
		if (array[temp] == temp) {   /*只有一个元素的环*/
			step++;
			visited[temp] = 1;
		}
		else {   /*开始新的环*/
			while (visited[temp]==0) {
				if (temp == 0) flag = 1;  /*判断环内有没有0*/
				visited[temp] = 1;
				temp = array[temp];
				step++;
			}
		}
		if (flag == 1) {
			steps[i] = 0-step;    /*使0所在的环使其为负值*/
			flag = 0;
		}
		else {
			steps[i] = step;
		}
		

	}
	int total = 0;
	for (int i = 0; i < N; i++) {
		if (steps[i] < 0) {   /*0所在的环*/
			total = total - steps[i]-1;
		}
		else if (steps[i] > 1) {  /*多元环*/
			total += steps[i]+1;
		}
	}
	printf("%d", total);
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值