1. 程式人生 > 實用技巧 >[PAT] A1089 Insert or Merge

[PAT] A1089 Insert or Merge

題目大意

給定原始序列和由某排序演算法產生的中間序列,請你判斷該演算法是插入演算法還是歸併演算法。首先在第1行中輸出“Insertion Sort”表示插入排序、或“Merge Sort”表示歸併排序;然後在第2行中輸出用該排序演算法再迭代一輪的結果序列。

思路

插入排序排到一半的序列滿足前半部分有序,後半部分和未排序時一樣。根據這個特點,先迴圈找到第一個不按順序的結點(下標k),然後迴圈看是否與原序列一樣。若i迴圈到了最後一個結點(i==n),則表明時插入排序,否則是歸併排序。
若是插入排序,則下一步是[0, k]有序,[k+1,n-1]和和原序列一樣,則呼叫sort將序列的[0, k+1)排序即可。
若是歸併排序,則從頭開始,模擬歸併排序的過程,以k = 2,4,8...為組排序,直找到和中間序列一致,再歸併一次即為輸出的結果。i從0到n/k,每次一段段得sort(a + i * k, a + (i + 1) * k);最後別忘記還有最後剩餘部分的sort(a + (n / k) * k, a + n);

判斷時別忘了part[i-1]和part[i]相等的情況!錯了兩百次了都!!!

AC程式碼

#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int>in, part;
int main() {
	int n, i, j;
	scanf("%d", &n);
	in.resize(n); part.resize(n);
	for (i = 0;i < n;i++)scanf("%d", &in[i]);
	for (i = 0;i < n;i++)scanf("%d", &part[i]);
	i = 1;
	while (i < n && part[i - 1] <= part[i])i++;//這裡part[i-1]等於part[i]時也要繼續迴圈!!!!!!
	int k = i; 
	while (i < n && in[i] == part[i])i++;
	if (i == n) {
		printf("Insertion Sort\n");
		sort(part.begin(), part.begin() + k + 1);
		printf("%d", part[0]);
		for (j = 1;j < n;j++)printf(" %d", part[j]);
	}
	else {
		printf("Merge Sort\n");
		vector<int>ans = in;
		int u = 2;
		while (ans != part) {

			for (j = 0;j < n / u;j++)
				sort(ans.begin() + j * u, ans.begin() + (j + 1) * u);
			sort(ans.begin() + j * u, ans.end());
			u = u * 2;
		}
		for (j = 0;j < n / u;j++)
			sort(ans.begin() + j * u, ans.begin() + (j + 1) * u);
		sort(ans.begin() + j * u, ans.end());
		printf("%d", ans[0]);
		for (j = 1;j < n;j++)printf(" %d", ans[j]);
	}
	return 0;
}