zoukankan      html  css  js  c++  java
  • 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;
        }
    };
    
  • 相关阅读:
    [Web 前端] CSS 盒子模型,绝对定位和相对定位
    [Android Pro] 跨平台反编译工具 jadx (ubuntu亲测 可用)
    [Web 前端] Jquery 复制元素,并修改属性, 追加到另一个元素后面
    [Web 前端 ] Jquery attr()方法 获取或修改 对象的属性值
    [Web 前端] Jquery实现可直接编辑的表格
    [Web 前端] td长度固定,内容过长,超过部分用省略号代替
    [Network] okhttp3与旧版本okhttp的区别分析
    [Android Pro] AndroidStudio IDE界面插件开发(进阶篇之Editor)
    graph embedding 使用方法
    win10 'make' 不是内部或外部命令
  • 原文地址:https://www.cnblogs.com/MagicConch/p/12179149.html
Copyright © 2011-2022 走看看