LeetCode 21.23.&&剑指 Offer II 078. 合并两个有序链表 | C语言版

LeetCode 21. 合并两个有序链表

题目描述

题目地址21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的
在这里插入图片描述

解题思路

思路一:使用栈
代码实现
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

/*
C初始动态分配语句 L.data=(ElemType*)malloc(sizeof(ElemType)*InitSize);
每个数据元素所占用存储空间的大小 sizeof(ElemType)
*/

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){

    //list1为空
    if(!list1) return list2;
    //list2为空
    if(!list2) return list1;
    
    struct ListNode* head=(struct ListNode*)malloc(sizeof(struct ListNode)),*t=head;

    while(list1 && list2){
        if(list1->val<list2->val){
            t->next=list1;
            list1=list1->next;
        }else{
            t->next=list2;
            list2=list2->next;
        }
        t=t->next;
    }

    //list2为空(遍历完毕)
    if(list1) t->next=list1;

    //list1为空(遍历完毕)
    if(list2) t->next=list2;

    return head->next;

}
运行结果

在这里插入图片描述

参考文章:

https://leetcode.cn/problems/merge-two-sorted-lists/solutions/126597/cliang-chong-fang-fa-chang-gui-di-gui-by-danny-50/?orderBy=most_votes&languageTags=c

思路二:减少遍历节点数
代码实现
在这里插入代码片
运行结果
参考文章:

LeetCode 剑指 Offer II 078. 合并排序链表

题目描述

题目地址剑指 Offer II 078. 合并排序链表
给定一个链表数组,每个链表都已经按升序排列。
请将所有链表合并到一个升序链表中,返回合并后的链表。
在这里插入图片描述

解题思路

思路一:分治思想,归并排序
代码实现
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 /*
 *利用归并排序的原理,采用分治思想:将k个已排序链表分成前k/2个已排序链表和后k/2个已排序链表,这两部分链表再继续递归地进行划分;递归到每组只剩一个链表时,再两两合并
 */

 //治:将链表合并
struct ListNode* merge(struct ListNode* a, struct ListNode* b){

    //虚拟头结点
    struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    //注意申请节点之后对结构体内的指针赋值,赋值为NULL总没问题
    dummy->next=NULL;
    //合并的新链表
    struct ListNode* x = dummy;

    //a=[1],[4],[5],[1]  b=[3],[4],[2],[6]

    while (a && b){
        //将小的数字放入到合并的新链表中(实现排序)
        if (a->val < b->val){
            x->next = a;
            a = a->next;
        }else{
            x->next = b;
            b = b->next;
        }
        x = x->next;
    }

    //如果链表a中还有元素(链表b中元素为空),将a中元素全部放入新链表x
    if (a) x->next = a;
    //如果链表b中还有元素(链表a中元素为空),将b中元素全部放入新链表x
    if (b) x->next = b;

    //x=[1,1,2,3,4,4,5,6]

    return dummy->next;
}

//分
struct ListNode* merge_sort(struct ListNode** lists, int l, int r){

    if (l == r) return lists[l];
    int mid = (l + r) / 2;

    //递归分割链表,直至每个链表只有一个元素
    struct ListNode* L = merge_sort(lists, l, mid);
    struct ListNode* R = merge_sort(lists, mid + 1, r);

    //l=[1],[4],[5],[1]  r=[3],[4],[2],[6]

    //将这些链表(只有一个元素)按照升序合并
    return merge(L, R);
}

struct ListNode* mergeKLists(struct ListNode** lists, int listsSize){
    //lists =[[1,4,5],[1,3,4],[2,6]]
    if (listsSize == 0) return NULL;
    return merge_sort(lists, 0, listsSize - 1);
}

运行结果

在这里插入图片描述

参考文章:

https://leetcode.cn/problems/vvXgSW/solutions/944453/cpython3java-1bian-li-zhu-ge-he-bing-2-b-xngx/?orderBy=most_votes&languageTags=cpp%2Cc

思路二:减少遍历节点数
代码实现
在这里插入代码片
运行结果
参考文章:

LeetCode 23. 合并K个升序链表

题目描述

题目地址23. 合并K个升序链表
给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。
在这里插入图片描述

解题思路

思路一:分治思想
代码实现
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

//治:合并两个有序链表
struct ListNode* merge(struct ListNode* l1, struct ListNode* l2){

    if(!l1) return l2;
    if(!l2) return l1;
    if(l1->val <= l2->val){
        l1->next = merge(l1->next, l2);
        return l1;
    }else{
        l2->next = merge(l1, l2->next);
        return l2;
    }

}

//分
struct ListNode* merge_sort(struct ListNode** lists, int l, int r){

    if (l == r) return lists[l];
    int mid = (l + r) / 2;

    //递归分割链表,直至每个链表只有一个元素
    struct ListNode* L = merge_sort(lists, l, mid);
    struct ListNode* R = merge_sort(lists, mid + 1, r);

    //将链表按照升序合并
    return merge(L, R);
}


struct ListNode* mergeKLists(struct ListNode** lists, int listsSize){
    if (listsSize == 0) return NULL;
    return merge_sort(lists, 0, listsSize - 1);
}
运行结果

在这里插入图片描述

参考文章:

https://leetcode.cn/problems/merge-k-sorted-lists/solutions/172800/c-you-xian-dui-lie-liang-liang-he-bing-fen-zhi-he-/?orderBy=most_votes&languageTags=cpp%2Cc

思路二:减少遍历节点数
代码实现
在这里插入代码片
运行结果
参考文章:

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李莲花*

多谢多谢,来自一名大学生的感谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值