• LeetCode(C++)刷题计划:21-合并两个有序链表


    21-合并两个有序链表

    @Author:CSU张扬
    @Email:csuzhangyang@gmail.com or csuzhangyang@qq.com

    Category Difficulty Pass rate Tags Companies
    algorithms Easy 57.92% linked-list amazon / apple / linkedin / microsoft

    1. 题目

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

    示例:
    
    输入:1->2->4, 1->3->4
    输出:1->1->2->3->4->4
    

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

    2. 解法

    2.1 解法一:归并排序

    1. 创建一个新的链表 h ,用于存储合并后的链表。
    2. 遍历两个链表。比较两者当前的 val 大小,小的则加入到 h 中,并向后移,另外一个链表不用移动。直至某一个链表遍历到尾部,结束。
    3. 此时肯定有一个链表没有遍历到尾部,将这个链表剩余的元素依次加入到 h 后面即可。

    执行用时: 8 ms, 在所有 cpp 提交中击败了96.15%的用户
    内存消耗: 9.1 MB, 在所有 cpp 提交中击败了73.70%的用户

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
            ListNode* h = new ListNode(0);
            ListNode* head = h;
            while(l1 && l2) {
                if (l1->val < l2->val) {
                    h->next = new ListNode(l1->val);
                    h = h->next;
                    l1 = l1->next;
                } else {
                    h->next = new ListNode(l2->val);
                    h = h->next;
                    l2 = l2->next;
                }
            }
            if (l1) {
                while(l1) {
                    h->next = new ListNode(l1->val);
                    h = h->next;
                    l1 = l1->next;
                }
            } else if (l2) {
                while(l2) {
                    h->next = new ListNode(l2->val);
                    h = h->next;
                    l2 = l2->next;
                }
            }
            ListNode* ptrDelete = head;
            head = head->next;
            delete ptrDelete;
            return head;
        }
    };
    

    2.2 解法二:递归(两种)

    2.2.1 简单递归

    参考zxyperfect

    1. 递归思路:
      我们每次从两个链表的头结点选出一个较小的放在结果中,并在原链表中删除该结点,然后继续比较两个链表。直至一个链表为空。
    2. 递归结束条件:
      当某个链表为空时,递归结束,但我们返回的是另一个链表。因为另一个链表剩下的肯定是值最大的那部分。例如:if(l1 == nullptr) { return l2; }

    执行用时: 12 ms, 在所有 cpp 提交中击败了69.38%的用户
    内存消耗: 9 MB, 在所有 cpp 提交中击败了74.60%的用户

    class Solution {
    public:
        ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
            if(l1 == nullptr){
                return l2;
            }
            if(l2 == nullptr){
                return l1;
            }
            if(l1->val <= l2->val){
                l1->next = mergeTwoLists(l1->next, l2);
                return l1;
            }
            else{
                l2->next = mergeTwoLists(l1, l2->next);
                return l2;
            }
        }
    };
    

    2.2.2 利用swap函数递归

    参考 StefanPochmann

    swap函数介绍:
    swap(a, b) :交换a和b。在此结构体中的意思就是 a->nextb->next 交换,a->valb->val 也交换。

    1. 首先注意,我们的合并后的链表是 a 头结点所指向的链表,也就是 a 所走过的位置, 都被按顺序加了进来。
    2. 总的思想就是:若 a->val > b->val ,就 swap(a, b) ,把 a 放到小的那个节点。
      反之,a 继续向所在节点后面移动,继续比较,a 会始终保持在较小的那个节点上。
    3. a 所在链表到达尾部时(a = nullptr),说明另外一个链表剩余的都是最大的几个值,我们这时仍需要 swap(a, b) ,将 a 放到另一个链表剩余的值上。
    4. 后续我会画个图例出来。

    执行用时 :8 ms, 在所有 cpp 提交中击败了95.91%的用户
    内存消耗 :8.7 MB, 在所有 cpp 提交中击败了97.11%的用户

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* mergeTwoLists(ListNode* a, ListNode* b) {
            if (!a || b && a->val > b->val) swap(a, b);
            if (a) a->next = mergeTwoLists(a->next, b);
            return a;
        }
    };
    
  • 相关阅读:
    React 之使用 fetch
    react-native 环境搭建
    create-react-app 配置 less
    React新的前端思维方式
    字体图标 —— IconMoon
    你不知道的javascript 之 >>
    前端的自我修养
    jquery 学习
    html的meta总结
    git基本操作 nginx基本操作
  • 原文地址:https://www.cnblogs.com/MagicConch/p/12179149.html
Copyright © 2020-2023  润新知