排序 Swap(0, i) 最小次数

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">	</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">最近在上数据结构和算法基础, 有一个附加题。要求如下:</span>

5-1 Sort with Swap(0, i)   (25分)

Given any permutation of the numbers {0, 1, 2,..., N1}, 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, ..., N1}. 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

看到题目,思考一番不难得出:Swap(0, i) 即不断的将0 所在的下标对应的数进行交换,以保证每一次交换都能有一个数字被放到正确的位置。

然而,这里面存在一些特殊情况,即 0 已经回到了Array[0], 而数组中别的数还没排序完成。

没有办法,只能选择用0 与第一个排序错误的数进行Swap, 而这次Swap是没有完成排序一个数的任务的,但我们别无选择。

在这样的思路下,我自己先写了一个程序,然而OJ系统的结果是:在一些例子的情况下运行超时。

代码如下:

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

int *Array, NumNotPos, NumSwap;
void Swap(int a, int b, int N);
void Sort(int N);
void Read(int N);


int main(int argc, char const *argv[])
{
	int N;
	scanf("%d", &N);
	Read(N);
	Sort(N);
	printf("%d\n", NumSwap);
	system("pause");
	return 0;
}

void Read(int N)
{
	Array = (int *)malloc(N * sizeof(int));
	int i = 0;
	while (i < N)
	{
		scanf("%d", &Array[i]);
		i++;
	}
	/*
	Array[0] = 3;
	Array[1] = 5;
	Array[2] = 7;
	Array[3] = 2;
	Array[4] = 6;
	Array[5] = 4;
	Array[6] = 9;
	Array[7] = 0;
	Array[8] = 8;
	Array[9] = 1;
	*/
}

void Sort(int N)
{
	int i = 0;
	while (i < N)
	{
		if (Array[i] != i)
			NumNotPos++;
		i++;
	}
	
	do
	{
		if (Array[0] == 0 && NumNotPos != 0)
		{
			int j = 1;
			while(Array[j] == j && j < N)
			{
				j++;
			}
			Swap(0, j, N);
			NumNotPos++;
		}

		if (NumNotPos != 0)
		{
			int j = 0;
			while (Array[j] != 0 && j < N)
				j++;
			Swap(0, j, N);
			NumNotPos--;
			if (Array[0] == 0)
				NumNotPos--;
		}
	} while (NumNotPos > 0);
}

void Swap(int a, int b, int N)
{
	NumSwap++;
	int i, temp, FirIndex, SecIndex;
	i = FirIndex = SecIndex = 0;
	while (i < N)
	{
		if (Array[i] == a)
			FirIndex = i;
		if (Array[i] == b)
			SecIndex = i;
		if (FirIndex && SecIndex)
			break;
		i++;
	}
	
 	temp = Array[FirIndex];
 	Array[FirIndex] = Array[SecIndex];
 	Array[SecIndex] = temp;
}

想了很久,自我感觉已经没法优化了,结果还是超时。。。

上google! 1s 出结果,找到了一个似乎和我一样在浙大上PTA的同学技术博客。

点击打开链接  http://blog.csdn.net/xyt8023y/article/details/47210245

搬运至此:

#include <stdio.h>  
  
int findNotOK(int* arr,int begin,int end)   //从begin开始往后寻找未到位的数  
{  
    for(int i=begin;i<end;i++)  
    {  
        if(arr[i]!=i)return i;  
    }  
    return 0;  
}  
  
int main()  
{  
    int n;  
    scanf("%d",&n);  
    int* arr = new int[n];  
    int i,t;  
  
    for(i=0;i<n;i++)  
    {  
        scanf("%d",&t);  
        arr[t]=i;  
    }  
    int tmp = 0;  
    int count=0;  
    int firstPos = 1;  
    firstPos = findNotOK(arr,firstPos,n);  
  
    while(firstPos)     //还有未到位的数字  
    {  
        if(arr[0]==0)       //如果0到位了,则与未到位的firstPos交换  
        {  
            arr[0] = arr[firstPos];  
            arr[firstPos] = 0;  
            count++;  
        }  
  
        while(arr[0]!=0)    //如果0不到位,则循环与自己所指向的值交换  
        {  
            tmp = arr[0];  
            arr[0] = arr[tmp];  
            arr[tmp] = tmp;  
            count++;  
        }  
        firstPos = findNotOK(arr,firstPos,n);       //此时0归位了,找到下一个未到位的数字  
    }  
    printf("%d\n",count);  
  
    return 0;  
}  
对比起来,思路上基本是一致的,但在确认排序完成和寻找Swap下标的实现上存在不同。但在浙大PTA中能够通过。

结论:自己的实现总存在着大量的循环确认未排序数的个数,并且循环寻找Swap下标。

对比第二份代码,我发现这样的循环存在太多的冗余信息。

而事实上确如第二份代码中的实现,第一个未排序完成数的下标,包含了两份信息:

1、排序是否完成

2、若没完成,Array[0] == 0 时0 的交换对象。

这确实值得我学习,在满足需求的情况下,精准的定位需要的信息量,而不是盲目的获取大量无用信息。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值