【PAT甲级】1089 Insert or Merge (25分)

解题过程的小记录,如有错误欢迎指出。

难度:四星(至今没搞懂,为什么过了实例代码却过不了测试点,而且一个都过不了 搞懂了!!!我是个憨憨orz!!!)

题目分析

给出一组数的初始状态和中途状态,要给出它是通过插入排序还是合并排序以达到中途状态的,并且要给出下一组状态

注意点

  1. 是要找出非递增的第一个数,然后将其进行插入,如:3 5 6 7 1的下一组是1 3 5 6 7
  2. 归并排序的非递归模板的初始值和边界点,需要了解
  3. sort排序一个下标从0开始的n个数字时,需要写成sort(num,num+n)

我的解题过程

思路

  1. 先求出插入排序的每一个状态,将数组转化为一个连续数字的字符串【注意:存储的字符串将格式设置为与输出格式一致,每个数字之间需要加入空格,这样也方便直接输出】,与中途字符串【也转化为输出格式的字符串】进行比较,当相同时,输出插入排序的下一个状态,结束程序
  2. 如果不是插入排序(也就是程序没有结束),就只能是合并排序,也将合并排序的每一个状态输入到字符串数组,进行与中途字符串的比较,相同就输出下一状态

bug

  1. 因为是采用字符串进行存储状态和比较,刚开始的时候没有将存储的数字转化为输出格式,而是傻傻的中间没有空格合在一起而且在结果输出的时候直接逐个进行输出(char by char orz),这就导致了我的代码在测试样例的时候不会出现问题(因为样例给出的数字都是单个数字),只要一碰到例子中是非单个数字的,按照我原来的存储方法就会出问题,导致测试点一个都过不了。
  2. 刚开始的时候对插入算法的理解也有误,因为如果按照顺序扫描数字逐个插入,当递增时,下一状态就不会发生变化,所以是要找到非递增的第一个进行插入
  3. 【陷阱】和初始状态一样的情况可能会产生多解,如初始数组为2 3 1 4,中途数组也为2 3 1 4,这组中途数组插入排序中会产生,归并中也会产生,不考虑这一点会有一个测试点过不了,当成插入排序可过(个人感觉这是一个题目的小bug)

代码

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>

using namespace std;

int n;
vector<string> insertion, mergesolution;//用于存储从原始开始每一次变化后的结果(不包括初始情况
vector<int> num;

string tostring(vector<int> nn) {
	string ans = "";
	for (int i = 0; i < nn.size(); i++) {
		if (i != 0) ans += " ";
		ans += to_string(nn[i]);
	}
	return ans;
}

void insertionSort() {
	vector<int> n1 = num;
	insertion.push_back(tostring(num));//
	for (int i = 0; i < n - 1; i++) {
		if (n1[i] <= n1[i + 1]) continue;
		sort(n1.begin(), n1.begin() + i + 2); 
		insertion.push_back(tostring(n1));
	}
}

void mergeSort() {
	for (int step = 2; step / 2 < n; step *= 2) {
		for (int i = 0; i < n; i += step) {
			sort(num.begin() + i, num.begin() + min(i + step, n));
		}
		mergesolution.push_back(tostring(num));
	}
}

int main()
{
	cin >> n;
	num.resize(n);
	string result = "";
	for (int i = 0; i < n; i++) {
		cin >> num[i];
	}
	for (int i = 0; i < n; i++) {//把目标序列转化为字符串进行比较
		int s;
		cin >> s;
		if (i != 0) result += " ";
		result += to_string(s);
	}
	insertionSort();
	for (int i = 0; i < insertion.size(); i++) {
		if (result == insertion[i]) {
			cout << "Insertion Sort" << endl;
			int j = 0;
			cout << insertion[i + 1];
			return 0;//确定是插入排序后就结束程序
		}
	}
	cout << "Merge Sort" << endl;
	mergeSort();
	for (int i = 0; i < mergesolution.size(); i++) {
		if (result == mergesolution[i]) {
			cout << mergesolution[i + 1];
			break;
		}
	}
    return 0;
}

dalao的代码

全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~

借鉴点

  1. 插入排序时可以采用柳神的代码方法,直接从开头开始,看数组是否递增,找到第一个非递增的点,看从这点开始是否和原数组保持一致,如若一致则是插入排序,将整个数字进行插入排序得到结果即可
  2. 时间允许的话可以用sort
  3. 合并排序的几个节点要背一下
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值