zoukankan      html  css  js  c++  java
  • 1067. 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. 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
    


    题目要求从一个由0到N-1的数据组成的线性表中,只允许进行0和*交换,来完成升序排序。

    一个自然的思路,就是让0把正确的元素换到自己的位置,例如开始0在8位置,则把8换过来,让原来8的位置换成0,这样多次重复就可完成元素的归位。需要注意的是,中途可能出现0出现在0位的情况,例如0在3号位,而3恰好在0号位,则0到了0位置,但是排序并未结束。

    这时候应该让0和最近的一个错误位置元素交换,然后继续上面的过程。

    还有个关键的问题是判断排序的结束, 注意到上面需要用到错误位置的元素,因此设计一个函数每次从位置1开始找错误元素,如果找不到返回0,注意不要从0开始找,这样只要找到的位置不是0,则说明还有未完成排序的元素,如果从0开始找,就无法判断是否排序结束了,因为我们用0判断是否找不到,并且我们不必担心第一个错误位置是0的情况,这个属于0在0位置但排序未完成的情况,在下面有处理。

    上面说的比较乱,总结如下:

    ①从位置1开始查找错误位置,找不到返回0,找到返回相应位置。

    ②如果查找函数返回0,说明排序结束,直接结束,否则进入③。

    ③如果0已经归位,但是排序没有结束,如果0不动无法继续排序,这时候让0和上面得到的错误位置交换,这个交换属于无用交换,但必须进行。

    ④在0没有归位的情况下,不断地把0的位置和应该在这个位置的元素交换,直到0归位,这时候再通过①的查找判断是否结束,没有结束则再继续③、④,直到满足找不到错误位置。


    下面的代码来自tiantangrenjian

    #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
    ",count);
    
        return 0;
    }
    


  • 相关阅读:
    Linux下C程序的反汇编【转】
    数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)【转】
    linux arm的存储分布那些事之一【转】
    linux arm mmu基础【转】
    linux 进程内存解析【转】
    如何更方便的查看Linux内核代码的更新记录【转】
    设备树解析【转】
    分析内核源码,设备树【转】
     Meltdown论文翻译【转】
    device tree --- #address-cells and #size-cells property【转】
  • 原文地址:https://www.cnblogs.com/aiwz/p/6154089.html
Copyright © 2011-2022 走看看