zoukankan      html  css  js  c++  java
  • 7-16 Sort with Swap(0, i)(25 分)

    7-16 Sort with Swap(0, i)(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 (≤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

    这道题用到了表排序中N个数字的排列由若干独立的环组成的知识。

    1.单元环swap(0,i)次数为0;

    2.有0的非单元环,swap(0,i)次数为n-1;

    3.无0的单元环,可以先把环里随便一个数和0交换一次,这样整个环就变成了含0的n+1个元素的非单元环,根据前面的情况2,次数为(n+1)-1,但还要加上把0换进去的那次,故swap(0,i)次数为n+1;

    代码如下:

    #include<iostream>
    #include<vector>
    #include<algorithm>
    using namespace std;
    int flag=0; // 记录circle是否含0;
    int main(){
    	int N; cin>>N;
    	// 储存数列
    	vector<int> sequence; 
    	
    	// 为了已知元素找下标而建立的position集合
    	// 其中pos[i]表示sequence中数值为i的元素的下标为pos[i]
    	vector<int> pos;   
    	
    	sequence.resize(N); // 不能少,为sequence创造N个空间
    	pos.reserve(N); // 不能少
    	
    	//读入数据和初始化pos
    	for(int i=0;i<N;i++) {
    		scanf("%d",&sequence[i]);
    		pos[sequence[i]]=i;
    	}
    	
    	//temp储存circle中第一个位置的元素
    	//swap_times记录swap(0,i)的次数
    	//elements_num记录circle中元素的个数
    	int temp,swap_times=0,elements_num=0;
    	for(int element=0;element<N;element++){
    	
    	//temp0用来进行下面的赋值活动
    		int element_circle=element; int temp0;
    		temp=sequence[element_circle];
    		
    		//每次进入circle前初始化elements_num为0;
    		elements_num=0; 
    		//若为单元环,则不进入while,故elements_num为0;
    		
    	    while(pos[element_circle]!=element_circle){//判断当前位置sequence[i]是否为i,即是否是单元环和环是否结束;若不是,则继续
    	    
    	    	if(sequence[element_circle]==0)        
    	    	flag=1;//记录该circle是否有0 
    	    	elements_num++; // 记录circle元素个数
    	    	if(pos[pos[element_circle]]!=pos[element_circle])//用于判断当前元素是否环的尾巴
    	    	sequence[element_circle]=element_circle; //不是尾巴
    	    	else
    	    	sequence[element_circle]=temp;// 是尾巴,用temp来赋值
    	    	
    	    	//下面部分用来更新pos和移动element_circle
    	    	temp0=element_circle;
    	    	element_circle=pos[element_circle];
    	    	pos[temp0]=temp0;
    	    	//
    			}
    		if(elements_num!=0){ // 判断是否是单元环
    		if(flag==1) swap_times+=elements_num-1; //判断circle是否有0,有0的非单元环移动elements-1次
    	    else swap_times+=elements_num+1; //无0的非单元环移动elements+1次
    		}
    		
    		//归零flag和elements_num
    	    flag=elements_num=0;
    	}
    	cout<<swap_times<<end;
    	return 0; 
    }
    

  • 相关阅读:
    一周自学动态站点设计
    【甘道夫】Apache Hadoop 2.5.0-cdh5.2.0 HDFS Quotas 配额控制
    linux系统管理命令--系统测试工具
    Atitit.异步编程 java .net php python js 对照
    项目开发经常使用PHP功能
    它们的定义app.config中间section节点和在执行中使用
    Android 它们的定义ListView实现底部和页下拉刷新刷新的顶
    vs2012连接sql2008(错误类型:Could not load file or assembly)
    管理不,因为你不是说经理
    java编程接口(5) ------ button和button组
  • 原文地址:https://www.cnblogs.com/A-Little-Nut/p/8067017.html
Copyright © 2011-2022 走看看