1. 程式人生 > >【PAT】1089. Insert or Merge (25)【排序】

【PAT】1089. Insert or Merge (25)【排序】

題目描述

According to Wikipedia:

Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. Each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain.

Merge sort works as follows: Divide the unsorted list into N sublists, each containing 1 element (a list of 1 element is considered sorted). Then repeatedly merge two adjacent sublists to produce new sorted sublists until there is only 1 sublist remaining.

Now given the initial sequence of integers, together with a sequence which is a result of several iterations of some sorting method, can you tell which sorting method we are using?

翻譯:根據Wikipedia上的描述:
重複插入排序過程,每次消耗一個輸入的元素,並且輸出序列長度加一。對於每次重複,將輸入資料中一個元素移走,找到它在排序佇列中的位置,並將其插入。重複此過程知道沒有多餘輸入元素。
歸併排序按照以下方式進行:將未排序佇列分成N個子表,每個包括1個元素(1個元素的表預設有序)。接著每次歸併兩個相鄰子表直到只剩1個子表。
現在給你一個初始序列,和一個某種排序方法進行幾次迭代後的結果,你可以說出我們是用什麼排序方法嗎?

INPUT FORMAT

Each input file contains one test case. For each case, the first line gives a positive integer N (<=100). Then in the next line, N integers are given as the initial sequence. The last line contains the partially sorted sequence of the N numbers. It is assumed that the target sequence is always ascending. All the numbers in a line are separated by a space.

翻譯:每個輸入檔案包含一組測試資料。對於每組輸入資料,第一行包括一個正整數N(<=100)。接著第二行給出由N個整陣列成的初始序列。最後一行包括N個數字的部分排序序列。假設目標序列總是升序排序。一行內所有數字之間用空格隔開。

OUTPUT FORMAT

For each test case, print in the first line either “Insertion Sort” or “Merge Sort” to indicate the method used to obtain the partial result. Then run this method for one more iteration and output in the second line the resulting sequence. It is guaranteed that the answer is unique for each test case. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.

翻譯:對於每組輸入資料,輸出一行“Insertion Sort”或“Merge Sort”來表示這個部分結果所用的方法。接著再執行一次該種方法的一次迭代,並在第二行輸出結果序列。保證每個測試資料的結果唯一。一行內所有數字之間用空格隔開,且行末尾不能有多餘空格。

Sample Input 1:

10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

Sample Output 1:

Insertion Sort
1 2 3 5 7 8 9 4 6 0

Sample Input 2:

10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6

Sample Output 2:

Merge Sort
1 2 3 8 4 5 7 9 0 6

解題思路

判斷是哪種排序:插入排序當遇到d[i] < d[i+1]時後面應全與原數列相同,若不相同,則為歸併排序。
進行插入排序:對1-i+1排序即可
進行歸併排序:先判斷d[2*k] >d[2*k+1] (2*k<=tempn(代表不超過N的2的最大指數) ),得到2*k與tempn的最小公倍數,即獲得題目歸併排序的區間大小,再乘以2,即為當前需要排序的區間大小。對每一段區間呼叫sort函式即可。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#define INF 99999999
using namespace std;
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}
int n,flag=0,Before[110],After[110];
int main(){
    scanf("%d",&n);
    int judge=0;
    for(int i=1;i<=n;i++) scanf("%d",&Before[i]);
    for(int i=1;i<=n;i++) {
        scanf("%d",&After[i]);
        if(flag==0&&After[i]<After[i-1])flag=i;
        if(flag!=0&&After[i]!=Before[i])judge=1;
    }
    if(judge==0){
        printf("Insertion Sort\n");
        sort(After+1,After+flag+1);
    }
    if(judge==1){
        printf("Merge Sort\n");
        int i,ccount=INF,tempn=1;
        while(tempn*2<=n)tempn*=2;
        for(i=2;i<=tempn;i+=2){ 
            if(After[i]>After[i+1]){
                ccount=min(ccount,gcd(tempn,i));
            }
        }
        ccount*=2;
        if(ccount==0)ccount=n;
        int q=1;
        for(q=1;q<=n;q+=ccount)
        {
            if(q+ccount<=n+1)
            {
                sort(After+q,After+q+ccount);
            }
        }
        if(q!=n+1)
        {
            sort(After+q-ccount,After+n+1);
        }
    }
    for(int i=1;i<n;i++)
    printf("%d ",After[i]);
    printf("%d\n",After[n]);
    exit(0);
}