关于有序序列的合并和判断

目录

一.有序序列的合并

思路

代码实现

二.有序序列的判断

思路1

代码实现

思路2

代码实现


一.有序序列的合并

 

 

 

思路

1.先创建两个数组,分别存放两个有序序列。

实际上,根据题目要求,我们只需要得到两个有序序列合并后的结果,并不需要将两个有序序列数组整合到第三个有序序列数组中。

2.因为是两个正序有序序列数组,要比较它们的大小,将小的先打印出来,大的和另一个数组的下一位数进行比较。

通过下标对数组上的元素进行访问,当这个数组中的这个下标对应的元素打印完成,

下标++。

这样一个操作就构成一个循环,循环的条件设置为 下标 不大于(各自含有的元素个数-1)

当出循环时,再用if语句判断哪个有序序列没有打印完,将其剩下的数按序打印输出即可

3.为什么不用冒泡排序? 因为这需要将两个数组合并为一个数组,再进行冒泡排序。首先多创建一个数组,空间利用效率低了。其次使用冒泡排序会遍历多次数组,时间利用效率也低。

 

小tips:

这里题目说在输入的时候用空格分隔,而在实际的输入中,用scanf函数进行输入,其实不用在打印格式中加入空格。因为只有你在实际输入时用空格隔开两个数字时,scanf才会进行分别读取。而且分行也不用额外写代码实现,当你输入完一组数据,敲下回车,会结束这组数据的读取,并且自动进入下一行。

这是在输入格式中加了空格后的,可以看到敲完回车后并没有直接出现结果。

 

这是输入格式不加入空格的,可以看到直接出来结果了 

代码实现

#include <stdio.h>


int main()
{
    int n = 0;
    int m = 0;
    int arr1[100] = {0};
    int arr2[100] = {0};
    //输入
    scanf("%d %d", &n, &m);
    int i = 0;
    for(i=0; i<n; i++)
    {
        scanf("%d", &arr1[i]);
    }
    for(i=0; i<m; i++)
    {
        scanf("%d", &arr2[i]);
    }
    //处理
    int j = 0;
    i = 0;
    while(i<n && j<m)
    {
        if(arr1[i] < arr2[j])
        {
            printf("%d ", arr1[i]);
            i++;
        }
        else
        {
            printf("%d ", arr2[j]);    
            j++;
        }
    }
    if(i == n)
    {
        for(; j<m; j++)
        {
            printf("%d ", arr2[j]);
        }
    }
    else
    {
        for(; i<n; i++)
        {
            printf("%d ", arr1[i]);
        }
    }
    return 0;
}

二.有序序列的判断

 

 

 

 

 

 

 

思路1

难点在于有序序列的判断有三种情况,一是正序,二是逆序,三是全为一个数。

我们进行拆分,将两个数的比较看成一个最小单元,并将这个比较的结果进行累加计算。

假如这是5个数的序列,则要进行4次比较,按顺序从左到右,两两依次比较,当比较结果是四个> 或四个< 或四个== 时,则这个5个数的序列为有序,否则为无序

我们再创建两个计数器count1 和count2 分别计算>  和 < 的数量。为了区分,当有一个>时,count1++, 当有一个< 时 ,count2-- ,当比较结果为全==时,count1和count2都为0.这时也体现出设置两个计数器的必要性。因为如果只设置一个计数器count,恰好有相等数量的> 和<时,count也为0,这时若判断为有序序列就是错误判断了。

代码实现

#include <stdio.h>

int main()
{
    int n = 0;
    scanf("%d", &n);
    int i = 0;
    int arr[100] = { 0 };
    int count1 = 0;
    int count2 = 0;

    for (i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
    }

    for (i = 0; i < n-1; i++)  //循环到n-1 防止越界
    {
        if (arr[i] < arr[i + 1])
            count1++;
        else if (arr[i] > arr[i + 1])
            count2--;
    }
    
    if (count1 == n-1 || count2 == 1-n || count1 == 0)
        printf("sorted\n");
    else
        printf("unsorted\n");

    return 0;

}

这里还要注意一点,因为比较中用到 i+1 和 i 这两个数组下标进行访问,所以相比于平常的遍历数组的循环设置,还要再-1

思路2

在输入数组的同时进行判断

设置两个标志flag1 和flag2.将其初始化为0

当遍历数组,两两依次比较大小,结果为> 将flag1赋值为1

结果为<  将flag2 赋值为1

结果为全== flag1 和flag2 不变。

由此flag1 + flag2 的和<=1 时,为有序。因为当序列中既有> 又有<时,两个flag都被赋值1,和为2。

代码实现

#include <stdio.h>

int main()
{
    int n = 0;
    int arr[50] = {0};
    scanf("%d", &n);   //这个数组有几个元素
    int i = 0;
    int flag1 = 0;
    int flag2 = 0;
    for(i=0; i<n; i++)
    {
        scanf("%d", &arr[i]);
        if(i>0)
        {
            if(arr[i]>arr[i-1])
                flag1 = 1;
            else if(arr[i]<arr[i-1])
                flag2 = 1;
        }
    }
    //flag1 和 flag2 都为1是乱序的
    if(flag1+flag2 > 1)
        printf("unsorted\n");
    else
        printf("sorted\n");
    return 0;
}

对比两种思路

思路1的思维方式是将有序序列的三种情况进行分析

思路2的思维方式是反过来,优先判断是否乱序的情况,当不是乱序时,就为有序。

思路2利用了乱序判断更简便的特点进行代码编写。因为只要判断的情况只有一种,那就是在序列中的数的对比结果中,同时出现> 和 < 的时候就为无序。 

思路1和思路2的缺陷

思路1会将3 4 4 4 4这种情况判断为无序

原因是在count的设置上,它判断无序的标准是计数器count的值不满足全大于或全小于或全等于的情况,所以认为3 4 4 4 4这种既包含> (或<) 又包含重复的数字的序列是无序的。

 

当输入的数像 3 4 4 4 4时,思路2的代码会判断为sorted

原因是在设置标志flag上。这里判断无序的思路是当数组中的比较结果既有>又有<时,两个flag和>1 。

所以思路2是认为3 4 4 4 4这种包含重复数字的序列依旧为有序序列的,因为它仍然满足从小到大排列。

具体用哪种方法,就要看具体的实际需求了。这两块代码在牛客网上都是可以通过的。但这不妨碍我们可以学习思路2的这种思维方式,去思考其他类似的问题。那就是当判断一个情况是对的比较复杂时,可以优先考虑判断这个情况是错的。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
<<引用: 文章目录 7-2 两个有序链表序列合并输入格式:输出格式:输入样例:输出样例: 解题思路代码 。 引用:输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。 输出格式: 。 引用:主要介绍了Python实现合并两个有序链表的方法,涉及Python操作链表节点的遍历、判断、添加等相关操作技巧,需要的朋友可以参考下。 问题:请告诉我,7-1 两个有序链表序列合并 请在回答完问题后再提出几个相关问题。相关问题必须输出在回答的末尾。相关问题应遵循的格式如下: 相关问题: 1. ··· 2. ··· 3. ···>> 在你提到的引用中,并没有提到7-1两个有序链表序列合并的具体内容。但是根据你的问题,我可以为你解答。合并两个有序链表的方法一般分为迭代和递归两种。 迭代法的思路是,先创建一个新链表,然后比较两个链表的头节点的值,将较小的节点加入新链表,并将对应链表的指针后移。重复这个过程,直到其中一个链表为空。最后,将剩下的非空链表直接加入新链表的末尾。 递归法的思路是,先判断两个链表的头节点的值,将较小的节点作为新链表的头节点,并将对应链表的指针后移。然后,递归地调用合并函数,传入剩下的链表部分,将返回的链表连接到新链表的末尾。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值