合并两个排序的链表

合并两个排序的链表

http://www.nowcoder.com/questionTerminal/d8b6b4358f774294a89de2a6ac4d9337

描述

这是一篇针对初学者的题解,共用2种方法解决。
知识点:单链表,递归
难度:一星


题解:

题目要求:给两个非递减单链表l1, l2,合并为一个非递减的单链表。

方法一:迭代版本求解

初始化:定义cur指向新链表的头结点
操作:

  1. 如果l1指向的结点值小于等于l2指向的结点值,则将l1指向的结点值链接到cur的next指针,然后l1指向下一个结点值
  2. 否则,让l2指向下一个结点值
  3. 循环步骤1,2,直到l1或者l2为nullptr
  4. 将l1或者l2剩下的部分链接到cur的后面

技巧

一般创建单链表,都会设一个虚拟头结点,也叫哨兵,因为这样每一个结点都有一个前驱结点。

代码

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        ListNode *vhead = new ListNode(-1);
        ListNode *cur = vhead;
        while (pHead1 && pHead2) {
            if (pHead1->val <= pHead2->val) {
                cur->next = pHead1;
                pHead1 = pHead1->next;
            }
            else {
                cur->next = pHead2;
                pHead2 = pHead2->next;
            }
            cur = cur->next;
        }
        cur->next = pHead1 ? pHead1 : pHead2;
        return vhead->next;
    }
};

时间复杂度:O(m+n),m,n分别为两个单链表的长度
空间复杂度:O(1)

方法二:递归版本

方法一的迭代版本,很好理解,代码也好写。但是有必要介绍一下递归版本,可以练习递归代码。
写递归代码,最重要的要明白递归函数的功能。可以不必关心递归函数的具体实现。
比如这个ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
函数功能:合并两个单链表,返回两个单链表头结点值小的那个节点。

如果知道了这个函数功能,那么接下来需要考虑2个问题:

  1. 递归函数结束的条件是什么?
  2. 递归函数一定是缩小递归区间的,那么下一步的递归区间是什么?
    对于问题1.对于链表就是,如果为,返回什么
    对于问题2,跟迭代方法中的一样,如果PHead1的所指节点值小于等于pHead2所指的结点值,那么phead1后续节点和pHead节点继续递归

    代码

    class Solution {
    public:
     ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
     {
         if (!pHead1) return pHead2;
         if (!pHead2) return pHead1;
         if (pHead1->val <= pHead2->val) {
             pHead1->next = Merge(pHead1->next, pHead2);
             return pHead1;
         }
         else {
             pHead2->next = Merge(pHead1, pHead2->next);
             return pHead2;
         }
     }
    };
    时间复杂度:O(m+n)
    空间复杂度:O(m+n),每一次递归,递归栈都会保存一个变量,最差情况会保存(m+n)个变量
全部评论
看不懂
2
送花
回复
分享
发布于 2021-11-01 19:31
我测试了一下1 3 5 , 2 4 6,第二种方法,链表遍历首个value值并不是1而是-842150451很大一个数,好像有点问题 代码如下: #include <iostream> #include <cstdlib> #include <string> using namespace std; //定义一个结构体 typedef struct ListNode { int value; struct ListNode* next; }ListNode; //创建n个链表 ListNode* CreateListNode(int n) { ListNode* head = new ListNode; ListNode *pre = head; for (int i = 0; i < n; i++) { ListNode* p = new ListNode;//p的作用是用来存输入节点信息 cin >> p->value; pre->next = p; // pre指针指向的下一个对象就是刚才输入的信息 pre = p;//pre保存当前的节点信息 p->next = NULL; //每次都将最后一个节点指向NULL } return head; } //显示链表 void DisplayListNode(ListNode* head) { ListNode *p = head->next; while (p != NULL) { cout << p->value << " "; p = p->next; } cout << "输出结束" << endl; } /* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* Merge(ListNode* pHead1, ListNode* pHead2) { //用递归方法做的话,要注意递归出口 //以及递归空间减小 //pHead1不为空,pHead2为空,将存好的pHead2返回 if (!pHead1) return pHead2; if (!pHead2) return pHead1; if (pHead1->value <= pHead2->value) { pHead1->next = Merge(pHead1->next, pHead2); return pHead1; } else { pHead2->next = Merge(pHead1, pHead2->next); return pHead2; } } }; int main() { int n1,n2; cin >> n1; ListNode*head1 = CreateListNode(n1); cin >> n2; ListNode*head2 = CreateListNode(n2); DisplayListNode(head1); DisplayListNode(head2); Solution t; ListNode* merge=t.Merge(head1, head2); DisplayListNode(merge); system("pause"); return 0; }</string></cstdlib></iostream>
1
送花
回复
分享
发布于 2021-06-19 10:42
秋招专场
校招火热招聘中
官网直投
“一般创建单链表,都会设一个虚拟头结点,也叫哨兵,因为这样每一个结点都有一个前驱结点。”完美解决需要费劲加各种判空逻辑的烦恼
2
送花
回复
分享
发布于 2022-03-02 20:26
啥都能跟递归扯一扯
1
送花
回复
分享
发布于 2022-03-01 18:05
哨兵节点可以理解vhead和cur都是指针,cur=vhead的意思是二者指向同一个结点,那么改变cur指向的链表结点时,由于vhead和cur指向同一个节点,vhead也会改变
1
送花
回复
分享
发布于 2023-02-16 19:37 山西
方法一 ListNode *vhead = new ListNode(-1);这句new申请的空间是不是应该自己最后delete释放一下?
点赞
送花
回复
分享
发布于 2021-01-26 14:03
我想问一下为什么方法1的时间复杂度是O(m+n) 可以认为是O(n)吗?题解要求的时间复杂度是O(n)
点赞
送花
回复
分享
发布于 2021-11-06 17:40
对递归的理解运用不是很熟
点赞
送花
回复
分享
发布于 2022-03-01 18:06
用了三个指针,空间复杂度还是O(1)吗?如果用Java,就要创建3个结点,空间复杂怎么保证
点赞
送花
回复
分享
发布于 2022-03-23 17:54
能不能给个c语言版的答案啊 无语了
点赞
送花
回复
分享
发布于 2022-04-14 00:24

相关推荐

127 12 评论
分享
牛客网
牛客企业服务