zoukankan      html  css  js  c++  java
  • PAT Basic 插⼊与归并(25) [two pointers]

    题目

    根据维基百科的定义:
    插⼊排序是迭代算法,逐⼀获得输⼊数据,逐步产⽣有序的输出序列。每步迭代中,算法从输⼊序列中取出⼀元素,将之插⼊有序序列中正确的位置。如此迭代直到全部元素有序。归并排序进⾏如下迭代操作:⾸先将原始序列看成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

    题目分析

    已知原始数组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;
    }
    
  • 相关阅读:
    如何学习一门新技术
    linux atoi
    linux switch 跳转到 ”跳转至 case 标号“ 的错误
    from unittest import TestCase
    ensure that both new and old access_token values are available within five minutes, so that third-party services are smoothly transitioned.
    .BigInteger
    408
    Convert a string into an ArrayBuffer
    Optimal asymmetric encryption padding 最优非对称加密填充(OAEP)
    https://tools.ietf.org/html/rfc8017
  • 原文地址:https://www.cnblogs.com/houzm/p/12257286.html
Copyright © 2011-2022 走看看