PAT Advanced 1089 Insert or Merge (25) [two pointers]

题目

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?
Input Specification:
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.
Output Specification:
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.
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

题目分析

已知原始数组a,和对a排序过程中数组b,判断是归并排序还是插入排序,并打印再进行一轮排序后的结果

解题思路

判断是归并排序还是插入排序--插入排序过程中数组特点:第一个非升序数字(假设其索引为i)后的剩余数字都与原数组中相同位置数字相同

思路 01

  1. 如果是插入排序,对[0,i+1]的数字进行排序就是下一轮插入排序的结果
  2. 如果是归并排序,从原始数组使用非递归归并代码执行归并过程,并在每一轮判断排序结果是否已经是题目中已知的数组b,若是,则再进行一轮归并即可得出结果

思路 02

  1. 对原始数组分别进行插入排序和归并排序,在每一轮结束后,判断排序结果是否已经是题目中已知的数组b,若是,则再进行一轮排序即可得出结果

Code

Code 01

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
	// 1 接收输入 
	int n, a[100], b[100], i, j;
	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> a[i];
	for (int i = 0; i < n; i++)
		cin >> b[i];
	// 2 判断是哪种排序
	for (i = 0; i < n - 1 && b[i] <= b[i + 1]; i++); //找到第一个非升序数字下标 
	for (j = i + 1; a[j] == b[j] && j < n; j++); //从非升序数字后,开始找第一个下标相同元素不同的下标 
	if (j == n) {// 若第一个非升序数字后所有元素都与原数组相同,是插入排序 
		cout << "Insertion Sort" << endl;
		sort(a, a + i + 2);
	} else {// 归并排序 
		cout << "Merge Sort" << endl;
		int k = 1, flag = 1;
		while(flag) {
			flag = 0;
			for (i = 0; i < n; i++) {
				if (a[i] != b[i])
					flag = 1;
			}
			k = k * 2;
			for (i = 0; i < n / k; i++) // 对左边模拟归并排序 
				sort(a + i * k, a + (i + 1) * k);
			sort(a + n / k * k, a + n); // 如果有右边剩余,对齐进行排序 
		}
	}
	// 3 打印数组 
	for (j = 0; j < n; j++) {
		if (j != 0) printf(" ");
		printf("%d", a[j]);
	}
	return 0;
}

Code 02

#include <iostream>
#include <algorithm>
using namespace std;
const int N=111;
int origin[N],tempOri[N],changed[N];
int n; //元素个数
// 判断数组是否相等
bool isSame(int A[],int B[]) {
	for(int i=0; i<n; i++)
		if(A[i]!=B[i])return false;
	return true;
}
// 打印数组
void showArray(int A[]) {
	for(int i=0; i<n; i++) {
		printf("%d",A[i]);
		if(i<n-1)printf(" ");
	}
	printf("
");
}
// 插入排序
bool insert_sort() {
	bool flag = false;
	for(int i=1; i<n; i++) {
		if(i!=1&&isSame(tempOri,changed)) {
			flag = true;
		}
		// 写法一:
		int j,temp = tempOri[i];
		for(j=i-1; j>=0; j--) {
			if(temp>=tempOri[j])break;
			else tempOri[j+1]=tempOri[j];
		}
		tempOri[j+1]=temp;
		// 写法二:
//		int j=i,temp = tempOri[i];
//		while(j>0&&tempOri[j-1]>temp){
//			tempOri[j]=tempOri[j-1];
//			j--;
//		}
//		tempOri[j]=temp;
		if(flag)return true;
	}
	return false;
}
// 归并排序
void merge_sort() {
	bool flag = false;
	for(int step=2; step/2<=n; step*=2) { // 每次步长扩大一倍
		if(step!=2&&isSame(tempOri,changed))
			flag = true;
		for(int i=0; i<n; i+=step)  // 一轮排序,分成很多step组
			sort(tempOri+i,tempOri+min(i+step,n)); //每个step组升序排序
		if(flag) {
			showArray(tempOri);
			return;
		}
	}
}
int main(int argc, char * argv[]) {
	scanf("%d",&n);
	for(int i=0; i<n; i++) {
		scanf("%d",&origin[i]);
		tempOri[i]=origin[i];
	}
	for(int i=0; i<n; i++) {
		scanf("%d",&changed[i]);
	}
	if(insert_sort()) {
		printf("Insertion Sort
");
		showArray(tempOri);
	} else {
		printf("Merge Sort
");
		for(int i=0; i<n; i++) {
			tempOri[i]=origin[i]; //还原tempOri数组
		}
		merge_sort();
	}
	return 0;
}
原文地址:https://www.cnblogs.com/houzm/p/12257262.html