PAT1067 Sort with Swap(0,*)

本文介绍了一种独特的排序方法,该方法仅允许交换0与其他元素,并提供了两种实现方案。第一种方法通过查找未就位的元素并进行交换实现,第二种方法采用更高效的交换策略达成相同效果。

就是要用一种独特的排序方式来把数列排序

这种排序方式是:只能交换0与其他的数

最直接的想法当然是把0和它所在位置的应该是什么数交换,比如0在a[3],那么当然是找到3然后与0交换,这样3就换到了正确的位置

如果0已经在a[0],那么就把它和数列中从左往右扫描的第一个没有在正确位置的数交换

这个思路是很容易想到的,但是不优化的话就会超时

一种比较简单的优化方法就是从左往右扫描,记下遇到的第一个没有在正确位置的数,记为flag,后面就可以利用这个flag来缩小寻找各种数需要扫描的范围

因为在flag之前的数(除了a[0])都已经在正确的位置了,所以就不用去管

于是就得到了下列代码(虽然还是有一个点会超时)

#include <stdio.h>
#include <stdlib.h>

int FindNot(int *a, int begin, int end);
int FindPos(int *a, int target,int begin, int length);

int main()
{
	int a[100000];
	int N, _;
	int temp, flag = 1, count = 0, zeropos, position;
	scanf("%d", &N);
	for(_ = 0; _<N; _++)
		scanf("%d",&a[_]);
	while(flag = FindNot(a, flag, N)){
		if(a[0] == 0){
			temp = a[0];
			a[0] = a[flag];
			a[flag] = temp;
			count++;
			continue;
		}
		while(a[0] != 0){
			zeropos = FindPos(a, 0, flag, N);
			position = FindPos(a, zeropos, flag, N);
			temp = a[position];
			a[position] = a[zeropos];
			a[zeropos] = temp;
			count++;
		}
	}
	printf("%d",count);
	return 0;
}

int FindNot(int *a, int begin, int end)
{
	int i;
	for(i = begin; i < end; i++)
		if(a[i] != i)
			return i;
	return 0;
}

int FindPos(int *a, int target, int begin, int length)
{
	if(a[0] == target)
		return 0;
	int i;
	for(i = begin; i < length; i++)
		if(a[i] == target)
			return i;
	return -1;
} 


剩下的那个测试点超时,但我想不出怎么优化了,于是就上网找了一下,很难理解的一种方法

因为上一种方法,如果0在a[i],那么还要寻找i所在位置,这个开销是比较大的,于是别人就用了一种等效的方法(虽然我还没有理解为什么可以这样等效)

在x次交换后0会回到编号为0的位置,而被交换的数也被换到相应的位置。

可以通过交换

(1)、编号为0的数

(2)、以编号为0的数为编号的那个数

直到0出现在编号为0的位置以达到相同的效果。然后依次扫描,直到获得一个没有在排好序的位置上的数,交换这个数和0。

虽然这种交换方法不是题义限定的交换,但是效果是相同的

AC代码如下:

#include <stdio.h>
#include <stdlib.h>

int FindNot(int *a, int begin, int end);

int main()
{
	int a[100000];
	int N, _;
	int temp, flag = 1, count = 0;
	scanf("%d", &N);
	for(_ = 0; _<N; _++)
		scanf("%d",&a[_]);
	while(flag = FindNot(a, flag, N)){
		if(a[0] == 0){
			temp = a[0];
			a[0] = a[flag];
			a[flag] = temp;
			count++;
		}
		while(a[0] != 0){
			temp = a[0];
			a[0] = a[temp];
			a[temp] = temp;
			count++;
		}
	}
	printf("%d",count);
	return 0;
}

int FindNot(int *a, int begin, int end)
{
	int i;
	for(i = begin; i < end; i++)
		if(a[i] != i)
			return i;
	return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值