【链表】合并两个有序链表(C语言)(LeetCode基础算法题)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解题时,主要解决以下几个问题。


①对两个有序链表里的数字进行综合排序,合二为一。

先分别遍历两表,求知长度:

	PNode p=l1;    int len1=0;
    PNode q=l2;    int len2=0;
    while (p!=NULL)   //分别求两个链表的长度
    {
        len1++;
        p=p->next;
    }
    p=l1;
    while (q!=NULL)
    {
        len2++;
        q=q->next;
    }
    q=l2;

创建一个judge数组,存放排序的所有数字。

	int sum=len1+len2;
    int judge[sum];

然后就进行整合排序。
当前遍历的结点val值,哪张表的大,就存入哪个值;如果相等,就都存入。
注意临界情况:有一张表遍历到了尾部,就不需要在比较大小了,另一张表直接全部录入就可以了。

	int i=0;

    while(p!=NULL && q!=NULL)
    {
        if(p->val==q->val)
        {
            judge[i++]=p->val;
            judge[i++]=q->val;
            p=p->next;
            q=q->next;
        }
        else if(p->val < q->val)
        {
            judge[i++]=p->val;
            p=p->next;
        }
        else if(p->val > q->val)
        {
            judge[i++]=q->val;
            q=q->next;
        }
        
        if (p==NULL && q!=NULL)
        {
            while(q!=NULL)
            {
                judge[i++]=q->val;
                q=q->next;
            }
        }
        else if (q==NULL && p!=NULL)
        {
            while(p!=NULL)
            {
                judge[i++]=p->val;
                p=p->next;
            }
        }
        else  continue;
    }

可以看到,这个过程是部分嵌套了双重循环的,但是不用担心,大多数时候内循环是不会执行的。内循环是处理最后的事情,内循环执行完毕后,外循环也就退出了。(p,q都指向NULL了)


②把排序好的数字置入链表中return。

一开始,我想要用malloc另外开辟一串链表,然后将这些数字一个一个存入,然后return。
但是,其实没有必要再申请空间了,现成的l1和l2不就是吗?我只要将l1和l2连起来,不就有一个长串了吗。

	p=l1;
    while(p->next!=NULL)
    {
        p=p->next;
    }
    p->next=l2;

接下来就是赋值了,很简单。

	p=l1;
    i=0;
    while(p!=NULL)
    {
        p->val=judge[i++];
        p=p->next;
    }

③特殊情况的讨论。

如果止步于上述程序,是会出现错误的。因为有一些特殊情况并没有考虑完整。问题出在这里:

 	int sum=len1+len2;
    int judge[sum];

如果sum==0,judge数组的创建就是错误的,也就是说,两表皆为空时,直接返回NULL就可以了。
同样的,如果其中一表为空,那么直接返回另一表就可以了。

	if (len1==0 && len2==0)   return NULL;
    else if (len1==0 && len2!=0)   return l2; 
    else if (len1!=0 && len2==0)   return l1;
    else  ;

将这段代码添加在创建judge数组之前,程序就完整无误了。


④完整代码和延伸

完整代码:

typedef struct ListNode* PNode;

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){

    PNode p=l1;    int len1=0;
    PNode q=l2;    int len2=0;
    while (p!=NULL)   //分别求两个链表的长度
    {
        len1++;
        p=p->next;
    }
    p=l1;
    while (q!=NULL)
    {
        len2++;
        q=q->next;
    }
    q=l2;

    if (len1==0 && len2==0)   return NULL;
    else if (len1==0 && len2!=0)   return l2; 
    else if (len1!=0 && len2==0)   return l1;
    else  ;

    int sum=len1+len2;
    int judge[sum];
    int i=0;

    while(p!=NULL && q!=NULL)
    {
        if(p->val==q->val)
        {
            judge[i++]=p->val;
            judge[i++]=q->val;
            p=p->next;
            q=q->next;
        }
        else if(p->val < q->val)
        {
            judge[i++]=p->val;
            p=p->next;
        }
        else if(p->val > q->val)
        {
            judge[i++]=q->val;
            q=q->next;
        }
        
        if (p==NULL && q!=NULL)
        {
            while(q!=NULL)
            {
                judge[i++]=q->val;
                q=q->next;
            }
        }
        else if (q==NULL && p!=NULL)
        {
            while(p!=NULL)
            {
                judge[i++]=p->val;
                p=p->next;
            }
        }
        else  continue;
    }
    /*
       for (i=0; i<=sum-1; i++)
       {
           printf("%d ",judge[i]);
       }
    */
    /*把两个链表连接,再重新复制一遍,就不用再额外申请空间了*/
    p=l1;
    while(p->next!=NULL)
    {
        p=p->next;
    }
    p->next=l2;

    p=l1;
    i=0;
    while(p!=NULL)
    {
        p->val=judge[i++];
        p=p->next;
    }

    return l1;
}

随便再讨论一下
如果给定的这两个表是乱序的,也要完成上述的任务,其实也好办。我们录入judge数组的时候,先全部录入,不排序。录入完毕后,在进行排序工作即可,后续同上。难度上并没有增加。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值