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

原创 2015年11月18日 00:00:13

<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 的交换对象。

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

10-排序6 Sort with Swap(0, i) (25分)

表排序的典型题目。 分析: /* 假设每个环的元素个数分别为m1, m2, ...  * 其中,单一元素的环说明了该元素在正确的位置上,不考虑。多元素的环,所有元素都不在正确的位置上。 ...

10-排序6 Sort with Swap(0, i)

题目 10-排序6 Sort with Swap(0, i) (25分) 分析 我刚开始想着直接排序。先试了几个例子,经过总结之后,觉得步骤应该是这样: 看0在不在位置0处(即得到0所在的位...

Java笔试题:只能进行0与其他数的swap操作的排序算法

题目:长度为N的数组乱序存放着0到N-1.现在只能进行0与其他数的 swap 操作,请设计并实现排序,必须通过交换实现排序。

08-排序5. Sort with Swap(0,*) (25)

Given any permutation of the numbers {0, 1, 2,..., N-1}, it is easy to sort them in increasing order...

PAT 数据结构 08-排序5. Sort with Swap(0,*) (25)

Given any permutation of the numbers {0, 1, 2,..., N-1}, it is easy to sort them in increasing order...

数组排序--计算最小交换次数

给定一个包含1-n的数列,我们通过交换任意两个元素给数列重新排序。求最少需要多少次交换,能把数组排成按1-n递增的顺序,其中,数组长度不超过100。 例如: 原数组是3,2,1, 我们只需要交换1...

[I0A]排序算法综合实例

本章将讲以下几种排序算法:插入排序,合并排序,堆排序,快速排序,计数排序。 所有排序算法最后结果皆为增序 ①插入排序,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中。 我们都知道一个数字...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)