JavaScript PAT乙级题解 1035 插入与归并

根据维基百科的定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

归并排序进行如下迭代操作:首先将原始序列看成 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);
    }
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值