根据维基百科的定义:
插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。
归并排序进行如下迭代操作:首先将原始序列看成 N 个只包含 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 个有序的序列。
现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?
输入格式:
输入在第一行给出正整数 N (≤100);随后一行给出原始序列的 N 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。
输出格式:
首先在第 1 行中输出Insertion Sort
表示插入排序、或Merge Sort
表示归并排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。
输入样例 1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
输出样例 1:
Insertion Sort
1 2 3 5 7 8 9 4 6 0
输入样例 2:
10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6
输出样例 2:
Merge Sort
1 2 3 8 4 5 7 9 0 6
题解如下:
22/25 case4错误
我讨厌排序!!!我也讨厌链表 我也讨厌算法
我的思路是先进行插入排序,每步结束后将排序完的序列与输入的中间序列进行比对,设置一个标志flg=0,用于判断是否找到相同的序列,如果找到了就令flg=1,再继续递归排序,下一步递归就需要输出结果序列了,输出完毕后flg=2,之后就不用再进行排序了;
如果插入排序进行完毕后flg还为0,那就说明使用的不是插入排序,需要进行归并排序。
我对这些排序基本上没使用过,就大学学过,也都忘得差不多了,就现场百度,感觉归并排序蛮复杂的,想好久都想不出来应该怎么写,就摆烂去找别人的归并代码,但是一般的归并算法好像跟这个题目的不太一样, 没办法用,我就开始想一些歪门邪道旁门左道了哈哈哈哈哈
其实没有必要按照归并算法一步一步的进行分解、排序、归并,我直接把每个数据都用数组框起来(按照题目的意思,应该是两两合并,如果是奇数就最后一个单着)然后遍历数组两两连接排序,再进行比对就可以了。
网上好像有更简单的办法,但是c语言代码我不太乐意看,拉倒吧就这样,进步一点点就行,多了脑容量不够
/**
* 2024/03/14
* 22/25
*/
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const num = 3;
let rows = [];
// 原始数据
let originalData = [];
// 中间数据
let midData = [];
// 结果序列
let resArr = [];
// 用于判断是否找到与输入的中间序列相同的序列
let flg = 0;
rl.on("line", function (data) {
rows.push(data);
if (num === rows.length) {
originalData = rows[1].split(" ");
midData = rows[2].split(" ");
insertSort(originalData);
// 如果执行了一遍插入排序算法后flg仍为0
// 则说明没有找到对应的中间序列,继续执行归并排序
if (flg === 0) {
originalData = rows[1].split(" ").map((el) => [el]);
mergeSort(originalData);
}
}
});
/**
* 插入排序算法
* @param arr
*/
function insertSort(arr) {
if (arr.length !== 0) {
if (resArr.length === 0) {
resArr.push(arr.shift());
} else {
const first = arr.shift();
for (let i = 0; i < resArr.length; i++) {
// 如果需要插入的元素first小于结果数组中的某一个元素,就把first插入到她的前面
if (first < resArr[i]) {
resArr.splice(i, 0, first);
break;
} else if (i === resArr.length - 1) {
// 如果遍历到结果数组的末尾都还没有找到比first大的数据
// 那就把first放在结果数组的末尾
resArr.push(first);
break;
}
}
if (resArr.concat(arr).join(" ") === rows[2]) {
// 找到了对应的中间数组
flg++;
console.log("Insertion Sort");
} else if (flg === 1) {
// 找到中间数组后求下一轮迭代的结果,并让flg自增,不再继续遍历
flg++;
console.log(resArr.concat(arr).join(" "));
}
}
// flg=2说明找到了对应的中间序列并输出了下一轮迭代结果,不需要继续遍历了
if (flg < 2) {
insertSort(arr);
}
}
}
/**
* 归并排序算法:
* 1. 先将整个数组分成两半,再分别将这两个数组分成两半,
* 直到每个数组中只有一个元素为止;(用二维数组存储这些数组,此步骤省略)
* 2. 相邻两两一组进行比较排序,比较完毕后放在同一个数组中;
* 3. 每次取数组的第一个元素进行比较,如果其中某个数组为空
* 则直接把另一个数组中的全部数据全部放到结果数组中(此步骤省略)
* 4. 由于是用的二维数组存储数据,这个结果数组的长度为1,则说明排序完毕
* @param arr
*/
function mergeSort(arr) {
if (arr.length > 1) {
// 投机取巧一下
for (let i = 0; i < arr.length - 1; i += 2) {
arr[i] = arr[i].concat(arr[i + 1]).sort((a, b) => a - b);
arr[i + 1] = [];
}
// 过滤掉空数据
const res = arr.filter((el) => el.length > 0);
// 判断得到的数据是否与中间序列相同
if (res.flat().join(" ") === rows[2]) {
flg++;
console.log("Merge Sort");
} else if (flg === 1) {
console.log(res.flat().join(" "));
flg++;
}
if (flg < 2) {
mergeSort(res);
}
}
}