排序次数

题目描述:

   小摩有一个N个数的数组,他想将数组从小到大 排好序,但是萌萌的小摩只会下面这个操作:任取数组中的一个数然后将它放置在数组的最后一个位置。问最少操作多少次可以使得数组从小到大有序?

输入描述

   首先输入一个正整数N,接下来的一行输入N个整数。(N <= 50, 每个数的绝对值小于等于1000)

输出描述

    输出一行操作数

解题思路

   这一道题是将只能将任意位置的元素放置到末尾,从而实现元素的排序。当一个元素后面存在小于它的元素的时候,就需要移动到末尾,所以还是要考察元素的相对大小。
   与只能将队首的元素移动到任意位置不同,因为在移动队首元素的题目中,只要在队列中遇到一个需要移动的元素,它的前面所有的元素都需要移动,而不考虑大小问题,所以直接遍历数组,依次寻找顺序段就可以。但是这道题中,当元素的相对大小发生改变,比如一个顺序段遇到一个小的元素导致顺序段的顺序性被破坏,却需要进一步判断这个顺序段中有哪些元素不用移动,这就增加了代码的复杂度。
   从另一个角度看,这道题要求的是求出排序所需要的最小操作数,如果先进行排序,然后将各个元素与其所应该在的位置比较,就可以发现移动的元素个数,这就是方法一。
   方法二也是从排序的角度思考,将一个数组排序就是一个元素放在这个数组其他所有比它小的元素的后面(也可以看作是消除逆序对)。所以可以考察每一个元素,找到最后一个小于它的位置,那么这之后就是这个元素应该放置的位置index,而index后面可能还有元素,所以为了将这个元素能够放置到对应的index之上,需要将这个元素放置到最后,然后把index之后的所有元素依次放到末尾,这样就把这个元素移动到了index这个位置上。按照这个思路,需要考察每一个元素的放置位置index,index将数组分为两部分,index后面所有元素需要移动,而前面的元素需要进一步考察是否要移动。这就是方法二。
   方法二中还有一点需要注意的就是在判断元素相对大小的时候关于相等关系的处理,在上面的描述中,简单称其为找到最后一个小于该元素的位置,这里忽略了等于的情况,关于等于的处理,如果这个元素确定需要移动,也就是前面存在小于它的元素,等于的时候也算作是一个可以移动的位置,这样就缩小了index后面需要移动的元素数量,如果前面没有小于它的元素,那么就不考虑等于的情况,极端情况下,数组中所有元素都相等,不考虑相等的情况下,就不需要移动任何元素。

代码实现

方法一:

#include <iostream>
#include <vector>
using namespace std;
#define maxn 10000

void MergeSort(int A[],int low,int mid,int high){
    int left_length=mid-low+1;
    int right_length=high-mid-1+1;
    int* LEFT=new int[left_length+1];
    int* RIGHT=new int[right_length+1];
    for(int i=0;i<left_length;i++)
        LEFT[i]=A[low+i];
    for(int i=0;i<right_length;i++)
        RIGHT[i]=A[mid+1+i];
    LEFT[left_length]=RIGHT[right_length]=maxn;
    int rightindex=0,leftindex=0;
    for(int i=low;i<=high;i++){
        if(LEFT[leftindex]<=RIGHT[rightindex]){
            A[i]=LEFT[leftindex++];
        }else{
            A[i]=RIGHT[rightindex++];
        }
    }
    return;
}


void binarySort(int A[],int low,int high){
    if(low==high)return;
    else{
        int mid=(high+low)/2;
        binarySort(A,low,mid);
        binarySort(A,mid+1,high);
        MergeSort(A,low,mid,high);
    }
}

int FindMin(int copy[],int data[],int n){
    int num=1000;
    int* visit=new int[2*num+1];
	for(int j=0;j<=2*num;j++)
		visit[j]=0;
    vector<vector<int> > range(2001);
    int index;
    int i;
	int total=0;
    for(i=0;i<n;i++){	
        index=copy[i]+num;	
        if(visit[index]==0){	
			visit[index]=1;
			for(int j=0;j<n;j++)
				if(data[j]==copy[i])
					range[index].push_back(j);											
			if(i>0){
				int last=copy[i-1]+num;
				total=0;	
				for(int k=0;k<range[index].size();k++){                  
					if(range[index][k]<range[last][range[last].size()-1]){
						total++;		
						}
				}
				if(total>0)
					break;  
			}
    
        }            
    }
	if(total==0) return 0;
    int k=i+1;
    while(copy[k]==copy[i] && k<n) k++; 
    return total+n-k;
}
int main(){
    int n;
    cin>>n;
    int* data=new int[n];
    int* copy=new int[n];
    for(int i=0;i<n;i++){
        cin>>data[i];
        copy[i]=data[i];
    } 
    binarySort(copy,0,n-1);
    int result=FindMin(copy,data,n);
    cout<<result<<endl;   
}

方法二:

#include <iostream>
using namespace std;
int cnt=0;
int data[51];
int main(){
	int n,i,j;
	cin>>n;
	for(i=0;i<n;i++)
		cin>>data[i];
	int end=n-1;
	int flag=-1;
	for(i=0;i<=end;i++){
		for(j=i+1;j<n;j++)
			if(data[i]>data[j]){
				flag=j;
			}else if(data[i]==data[j]&&flag!=-1){
				flag=j;
			}
		if(flag!=-1){
			cnt++;
			if(end>flag)
				end=flag;
			flag=-1;			
		}
	}
	cout<<cnt+n-end-1<<endl;
	return 0;
}
发布了16 篇原创文章 · 获赞 0 · 访问量 337

猜你喜欢

转载自blog.csdn.net/qq_41922018/article/details/104316424