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 均按 非递减顺序 排列

题解

迭代法

  1. 题解

合并两个有序链表的问题可以通过多种方法解决,但最常见的方法是使用迭代。以下是解决这个问题的一般思路:

  • 定义节点结构:首先定义链表节点的数据结构,通常包含节点的值和指向下一个节点的指针。

  • 初始化哑节点:创建一个哑节点(dummy node),它将作为合并后链表的前驱节点。使用哑节点的好处是可以直接返回哑节点的下一个节点作为合并后的链表的头节点。

  • 迭代合并:使用两个指针分别指向两个链表的当前节点,比较它们的值,将较小的节点连接到结果链表上,并将该节点的指针向前移动一位。

  • 处理剩余节点:当其中一个链表遍历完成后,将另一个链表剩余的部分直接连接到结果链表的末尾。

  • 返回结果:返回哑节点的下一个节点,即合并后链表的头节点。

  1. 复杂度:时间复杂度O(m+n),其中 n 和 m 分别为两个链表的长度。因为每次循环迭代中,l1 和 l2 只有一个元素会被放进合并链表中, 因此 while 循环的次数不会超过两个链表的长度之和。所有其他操作的时间复杂度都是常数级别的;空间复杂度O(1),只需要常数的空间存放若干变量。

  2. 过程:

  • 创建哑节点:ListNode* dummy = new ListNode(0);
  • 初始化尾指针:ListNode* tail = dummy;
  • 迭代比较:使用一个循环,当两个链表的当前节点都不为空时,进行以下操作:
    • 比较两个链表当前节点的值。
    • 将较小节点连接到tail的后面。
    • 移动tail和较小节点的指针。
  • 连接剩余节点:当其中一个链表的节点为空时,将另一个链表的剩余部分直接连接到tail后面。
  • 返回结果:返回dummy->next作为合并后链表的头节点。
  1. c++ demo
cpp 复制代码
#include <iostream>

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        // 创建一个哑节点,作为合并后链表的起始点
        ListNode* dummy = new ListNode(0);
        ListNode* tail = dummy;

        // 用哑节点的 next 指针来逐步构建合并后的链表
        while (l1 != nullptr && l2 != nullptr) {
            if (l1->val < l2->val) {
                tail->next = l1;
                l1 = l1->next;
            }
            else {
                tail->next = l2;
                l2 = l2->next;
            }
            tail = tail->next;
        }

        // 将剩余的非空链表接在合并后的链表后面
        if (l1 != nullptr) {
            tail->next = l1;
        }
        else {
            tail->next = l2;
        }

        // 返回合并后的链表的头节点
        ListNode* result = dummy->next;
        delete dummy; // 释放哑节点
        return result;
    }
};

int main() {
    // 测试代码
    ListNode* l1 = new ListNode(1);
    l1->next = new ListNode(2);
    l1->next->next = new ListNode(4);

    ListNode* l2 = new ListNode(1);
    l2->next = new ListNode(3);
    l2->next->next = new ListNode(4);

    Solution solution;
    ListNode* mergedList = solution.mergeTwoLists(l1, l2);

    // 打印合并后的链表
    while (mergedList != nullptr) {
        std::cout << mergedList->val << " ";
        ListNode* temp = mergedList;
        mergedList = mergedList->next;
        delete temp; // 释放节点
    }
    std::cout << std::endl;

    return 0;
}
  • 输出结果:

1 1 2 3 4 4

相关推荐
Lenyiin25 分钟前
02.06、回文链表
数据结构·leetcode·链表
爪哇学长28 分钟前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法
爱摸鱼的孔乙己30 分钟前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
Dola_Pan32 分钟前
C语言:数组转换指针的时机
c语言·开发语言·算法
繁依Fanyi1 小时前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse
烦躁的大鼻嘎1 小时前
模拟算法实例讲解:从理论到实践的编程之旅
数据结构·c++·算法·leetcode
IU宝1 小时前
C/C++内存管理
java·c语言·c++
fhvyxyci1 小时前
【C++之STL】摸清 string 的模拟实现(下)
开发语言·c++·string
C++忠实粉丝1 小时前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
古月居GYH1 小时前
在C++上实现反射用法
java·开发语言·c++