当前位置: 首页 > news >正文

【C/C++】合并两个有序链表 (leetcode T21)

核心考点预览:链表 (双指针)  技巧:虚拟头结点

题目描述:

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

示例:

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

提示:

•      两个链表的节点数目范围是 [0, 50]

•      -100 <= Node.val <= 100

•      l1 和 l2 均按 非递减顺序 排列

详细解答:

// 定义链表节点结构
struct ListNode {
    int val; // 节点值
    struct ListNode *next; // 下一个节点指针
};

// 合并两个升序链表
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    struct ListNode *p1 = list1, *p2 = list2; // 初始化指向两个链表的指针
    struct ListNode* res = (struct ListNode*)malloc(sizeof(struct ListNode)); // 结果链表头节点
    struct ListNode* p = res; // p指针用于构建结果链表

    // 遍历两个链表,逐个比较节点值,合并到结果链表
    while (p1 != NULL && p2 != NULL) {
        // 如果list1当前节点小于list2当前节点
        if (p1->val < p2->val) {
            p->next = p1; // 将list1的当前节点链接到结果链表
            p = p1; // 更新p指针,指向list1当前节点
            p1 = p1->next; // list1向后移动一位
        } 
        // 如果list1当前节点等于list2当前节点
        else if (p1->val == p2->val) {
            p->next = p1; // 将list1的当前节点链接到结果链表
            p = p1; // 更新p指针,指向list1当前节点
            p1 = p1->next; // list1向后移动一位

            p->next = p2; // 将list2的当前节点链接到结果链表
            p = p2; // 更新p指针,指向list2当前节点
            p2 = p2->next; // list2向后移动一位
        }
        // 如果list2当前节点小于list1当前节点
        else {
            p->next = p2; // 将list2的当前节点链接到结果链表
            p = p2; // 更新p指针,指向list2当前节点
            p2 = p2->next; // list2向后移动一位
        }
    }

    // 如果list1遍历完,直接将剩余的list2链接到结果链表
    if (p1 == NULL) {
        p->next = p2;
    }
    // 如果list2遍历完,直接将剩余的list1链接到结果链表
    if (p2 == NULL) {
        p->next = p1;
    }

    // 返回合并后的链表,从res->next开始
    return res->next;
}

这么写中间有些繁琐,我们可以如此修改:

// 定义链表节点结构
struct ListNode {
    int val; // 节点值
    struct ListNode *next; // 下一个节点指针
};

// 合并两个升序链表
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    struct ListNode *p1 = list1, *p2 = list2; // 初始化指向两个链表的指针
    struct ListNode* res = (struct ListNode*)malloc(sizeof(struct ListNode)); // 结果链表头节点
    struct ListNode* p = res; // p指针用于构建结果链表

    // 遍历两个链表,逐个比较节点值,合并到结果链表
   while (p1 != nullptr && p2 != nullptr) {

            // 比较 p1 和 p2 两个指针
            // 将值较小的的节点接到 p 指针
            if (p1->val > p2->val) {
                p->next = p2;
                p2 = p2->next;
            } else {
                p->next = p1;
                p1 = p1->next;
            }
            // p 指针不断前进
            p = p->next;
        }

    // 如果list1遍历完,直接将剩余的list2链接到结果链表
    if (p1 == NULL) {
        p->next = p2;
    }
    // 如果list2遍历完,直接将剩余的list1链接到结果链表
    if (p2 == NULL) {
        p->next = p1;
    }

    // 返回合并后的链表,从res->next开始
    return res->next;
}

思路分析

  • 链表合并:合并两个升序链表,关键在于逐个比较两个链表的节点,将较小的节点添加到结果链表中。

  • 时间复杂度:由于两个链表都是升序的,每次合并操作都可以直接选取较小的元素,因此该方法的时间复杂度为 O(n + m),其中 nm 分别是两个链表的长度。

考点分析

  1. 链表操作:熟悉链表的遍历和合并操作。

  2. 指针操作:如何通过指针操作将两个链表合并为一个新链表。

  3. 边界情况:处理其中一个链表为空的情况,确保代码的健壮性。

相关文章:

  • QML ScrollBar如何一直保持到最底部
  • 【C语言】fgetpos函数用法介绍
  • C# 中DevExpress的GridView中Appearance 属性
  • 搅局外卖,京东连出三张牌
  • Selenium实战案例2:东方财富网股吧评论爬取
  • 解决 Plugin ‘org.springframework.boot:spring-boot-maven-plugin:‘ not found
  • Prompt:创造性的系统分析者
  • 前端面试之Box盒子布局:核心知识与实战解析
  • 单调栈刷题
  • 1.21作业
  • 除了Axios,如何用fetch处理403错误?
  • 懒人美食帮(springboot论文源码调试讲解)
  • 【记录55】多个参数查询,无用参数不记查询
  • go 通过ssh连接linux golang.org/x/crypto/ssh
  • 网络安全设备防护原理 网络安全防护装置
  • WARNING: pip is configured with locations that require TLS/SSL
  • C语言的指针常量、常量指针、指针函数、函数指针的区别
  • 去中心化协作智能生态系统设计
  • 【Flink实战】Flink网络内存和托管内存
  • 可视化工具SciChart如何结合Deepseek快速创建一个React仪表板?
  • 特朗普与普京通话前夕,英美法德意领导人通话讨论俄乌问题
  • 国家统计局:4月全国城镇调查失业率为5.1%,比上月下降0.1个百分点
  • 建筑瞭望|从黄浦江畔趸船改造看航运设施的升级与利用
  • 经济日报:政府采购监管篱笆要扎得更牢
  • 证监会披露两起操纵市场处罚结果,今年来涉操纵股票罚没金额超7.5亿元
  • 从良渚到三星堆:一江水串起了5000年的文明对话