双指针优化

  1. 第一题
    1. 输入格式:
    2. 输出格式:
    3. 输入样例:
    4. 输出样例:
  2. 归并与插入
    1. 输入格式:
    2. 输出格式:
    3. 输入样例 1:
    4. 输出样例 1:
    5. 输入样例 2:
    6. 输出样例 2:

完美数列

第一题

给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 Mm**p,则称这个数列是完美数列。

现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。

输入格式:

输入第一行给出两个正整数 Np,其中 N(≤105)是输入的正整数的个数,p(≤109)是给定的参数。第二行给出 N 个正整数,每个数不超过 109。

输出格式:

在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。

输入样例:

10 8
2 3 20 4 5 1 6 7 8 9

输出样例:

8

题目分析:原先我的想法是假设最长数列就是n,然后有序数组进行两端判断。想法是有,但是代码不知道怎么写

柳神是用双指针,这题其实双指针的时间复杂度都能上n^2^了,所以这里双指针要优化一下,用res来存放当前最长长度,

第一重循环用i=0~n,第二层循环j就不能从0开始了否则太慢了,而且重复了。

第二重循环用j=i+res~n

第二重循环中判断到不符合条件就直接跳出了,因为这是个有序数组,之后的数据也都不成立了。

所以做这两个优化后,效率杠杠的👍

#include<iostream>
#include<algorithm>
using namespace std;
int main(void){
    int n;
    long p;
    cin >> n >> p;
    int a[n],i,j;
    for(i = 0; i < n ;i++) cin >> a[i];
    sort(a,a+n);
    int tmp = 0,res = 0;
    for(i = 0; i < n ;i++){
        for(j=i + res;j < n;j++)  
            if(a[i] * p >= a[j] && (tmp = j - i + 1) > res)  res = tmp;
            else break;
    }
    cout << res;
    return 0;
}

归并与插入

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

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

题目分析:

这题由于插入排序是从后往前的,所以插入排序的中间序列一定是,前段有序,后段和原序列相同。

归并排序的话没有直观的规律,这里不是插入就是归并了,极端情况的数据没有意义

这里归并排序的下一个序列,由于无法判断是第几次归并,所以只能用原序列进行一次次归并比较中间序列,直到全部吻合

这里值得学习的是,用c++的sort函数,直接忽略了插入排序和归并排序的具体排序细节,运行效率可能没有她两好,不过开发效率很香

#include<iostream>
#include<algorithm>
using namespace std;
int main(void){
        int n;
        cin >> n;
        int a[n],b[n],i,j;
        for(i=0;i < n;i++) cin >> a[i];
        for(i=0;i < n;i++) cin >> b[i];
        for(i=0;b[i] <= b[i+1];i++);
        for(j=i + 1;b[j] == a[j] && j < n;j++);
        if(j == n){
            cout << "Insertion Sort" << endl;
            sort(a,a+i+2);
        }else{
            cout << "Merge Sort" << endl;
            int flag = 1 , k = 1;
            while(flag){
                flag = 0;
                for(i = 0; i < n ; i++) if(a[i] != b[i]) flag = 1;
                k *= 2;
                for(i = 0; i < n / k ; i++) sort(a + i * k, a + (i+1)*k );
                sort(a + n / k * k, a + n); // n / k 不整除的情况下,剩余部分给计算进去 
            }
        }
        for(i=0;i < n;i++) {
            if(i != 0) cout << " ";
            cout << a[i];
        }
        return 0;
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 jaytp@qq.com

×

喜欢就点赞,疼爱就打赏