IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> (LeetCode)合并两个有序链表——C语言 -> 正文阅读

[数据结构与算法](LeetCode)合并两个有序链表——C语言

题目要求

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。?

示例 1:


输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例 2:

输入:l1 = [ ], l2 = [ ]
输出:[ ]
示例 3:

输入:l1 = [ ], l2 = [0]
输出:[0]
?

提示:

两个链表的节点数目范围是 [0, 50]
-100 <= Node.val <= 100
l1 和 l2 均按 非递减顺序 排列

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/merge-two-sorted-lists

?

又是一个关于链表的题目,通过之前的几篇博客的讲解,大家对链表应该有比较熟悉的理解,因此对于本篇的讲解应该更容易理解。

题目理解以及思路分析

(一) 这个题目其实难度已经降低了,题目已经给出了 升序 的两个链表,也就是说链表的顺序已经排好了,我们只需要将其按照 升序 的顺序合并即可。

(二) 相信看到这,很多读者都有了思路,比如我们先随便将两个链表合并,然后通过一个顺序排列的代码来实现排序,这样的思路是正确的,但是本篇要讲的是另外一种方法。

(三) 我们要充分利用两个链表的 升序 的这个性质,我们先不着急把两个链表合并,我们先将两个链表的数据一个一个的进行比较,小的就放入新的链表里,然后接着下一轮的比较,以此类推。

这只是我们的设想,目前来看没有什么问题,但是在实现代码的过程中会不会出现新的问题?如果出现了问题,那我们该怎么去解决呢?

代码实现

我们先来实现主要功能的代码,入下:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    struct ListNode* ans = (struct ListNode *)malloc(sizeof(struct ListNode));
    struct ListNode* p1 = list1, * p2 = list2; 
    struct ListNode* rep = ans;
     

        if((p1 -> val) <= ( p2 -> val))
        {
            rep -> next = p1;
            rep = p1;
            p1 = p1 -> next;
            length1--;
        }
        else
        { 
          rep -> next = p2;
          rep = p2; 
          p2 = p2 -> next;
          length2--;
        }

? ? ? ?

        if((p1 -> val) <= ( p2 -> val))
        {
            rep -> next = p1;
            rep = p1;
            p1 = p1 -> next;
            length1--;
        }
        else
        { 
          rep -> next = p2;
          rep = p2; 
          p2 = p2 -> next;
          length2--;
        }

这一步便是比较的步骤,同时将较小的数字放进新的链表中。

但是,细心的读者已经发现了问题?这个判断什么时候停止呢?,链表是有限的,而且两个链表的长度未必相同,如何保证每次比较都是两个链表之间的比较呢?

没错,这就是代码实现中的问题。既然问题我们已经发现了,那就该想想如何解决问题。

不要忘了一个重要的性质——两个链表都是 升序

我们可以先求出两个链表的长度分别是多少,在链表之间进行比较时,总有一个链表里面的数字最先全部放入新的链表中,这时比较停止,剩余链表的数字仍然是 升序 排列,因此全部依次放入新的链表中即可。

怎么样?现在是不是突然觉得 升序 这个条件是很关键的性质了!这样我们的思路就是完整的了,下面我们来进行分部的代码讲解。

分部代码讲解

第一部分

int Length(struct ListNode*head)
  {
      int length = 0;
      while(head)
      {
        length++;
        head = head->next;
      }
      return length;
  }

这一步是定义一个函数,用来求每个链表的长度。在之前的博客中有讲过,这里便不在过多的讲解。

第二部分

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    struct ListNode* ans = (struct ListNode *)malloc(sizeof(struct ListNode));
    struct ListNode* p1 = list1, * p2 = list2; //定义
    struct ListNode* rep = ans;  //定义
    int length1,length2;  //定义 list1 和 list2 的对应的长度
    length1 = Length(p1); //调用函数
    length2 = Length(p2); //调用函数

?这一步主要是定义一些变量,调用上面定义的求长度的函数,为下面做铺垫。

第三部分

    while(length1 && length2) //当 length1 和 length2 中有一个为 0 ,则循环结束
    {
        //比较此时两个链表对应的值的大小
        if((p1 -> val) <= ( p2 -> val))  
        {
          rep -> next = p1;
          rep = p1;  //较小的值放入新的链表中
          p1 = p1 -> next;  //移位到链表的下一个数字
          length1--;  //链表长度减一
        }
        else
        { 
          rep -> next = p2;
          rep = p2; //较小的值放入新的链表中
          p2 = p2->next; //移位到链表的下一个数字
          length2--;  //链表长度减一
        }
    }

?第四部分

    if(length1 == 0)
       { rep -> next = p2 ; }
    else if(length2 == 0)
        { rep -> next = p1; } 
    return ans->next;
}

第四部分的实现上面讲解过,因为两个链表都是 升序 ,因此剩余的链表数据直接依次放入新的链表中即可。

return ans->next;

这一部分要特别注意,最后返回链表一定要从 ans -> next ,而不能直接返回 ans 。?

第五部分

完整的代码:

int Length(struct ListNode*head)
  {
      int length = 0;
      while(head)
      {
        length++;
        head = head->next;
      }
      return length;
  }
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    struct ListNode* ans = (struct ListNode *)malloc(sizeof(struct ListNode));
    struct ListNode* p1 = list1, * p2 = list2; //定义
    struct ListNode* rep = ans;  //定义
    int length1,length2;  //定义 list1 和 list2 的对应的长度
    length1 = Length(p1); //调用函数
    length2 = Length(p2); //调用函数
    while(length1 && length2) //当 length1 和 length2 中有一个为 0 ,则循环结束
    {
        //比较此时两个链表对应的值的大小
        if((p1 -> val) <= ( p2 -> val))  
        {
          rep -> next = p1;
          rep = p1;  //较小的值放入新的链表中
          p1 = p1 -> next;  //移位到链表的下一个数字
          length1--;  //链表长度减一
        }
        else
        { 
          rep -> next = p2;
          rep = p2; //较小的值放入新的链表中
          p2 = p2->next; //移位到链表的下一个数字
          length2--;  //链表长度减一
        }
    }
    if(length1 == 0)
       { rep -> next = p2 ; }
    else if(length2 == 0)
        { rep -> next = p1; } 
    return ans->next;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:13:18  更:2022-07-04 23:15:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:49:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码