• [LeetCode] 21. Merge Two Sorted Lists


    Description

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

    Example:

    Input: 1->2->4, 1->3->4
    Output: 1->1->2->3->4->4
    

    Analyse

    合并两个有序的链表l1l2

    最简单的做法是新建一个链表l3,从l1l2中获取最小的元素,插入新链表,其中一个链表的元素用完后,将另一个链表全部插入l3

    时间复杂度O(m+n) (m,n为l1l2长度)

    最大比较次数
    m + n - 1
    l3长度为m+n,每比较一次l3长度+1,最后一个元素不用比较

        1   3   5  7
        | / | / | /
        2   4   6
    

    最小比较次数
    min(m, n)

        1   3
        | /
        4   5   6
    

    Code

    写出第一个版本,这个版本耗时长,消耗的内存也大,原因是新链表l3中的每个节点都是新建的,这其实没必要,可以改为重复使用l1,l2中的节点

     ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
     {
        ListNode* l3 = new ListNode(NULL);
        ListNode* cur = l3;
        while (l1 || l2)
        {
            ListNode *tmp = new ListNode(NULL);
    
            if (!l1) {cur->next = l2; break;}
            if (!l2) {cur->next = l1; break;}
    
            if (l1->val < l2->val)
            {
                tmp->val = l1->val;
                l1 = l1->next;
            }
            else
            {
                tmp->val = l2->val;
                l2 = l2->next;
            }
    
            cur->next = tmp;
            cur = cur->next;
        }
    
        return l3->next;
    }
    

    做一些修改,重复利用l1, l2中的节点,这样就能够faster than 99%了

    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
    {
        ListNode* result = new ListNode(0);
        ListNode* cur = result;
        while (l1 && l2)
        {
            if (l1->val < l2->val)
            {
                cur->next = l1;
                l1 = l1->next;
            }
            else
            {
                cur->next = l2;
                l2 = l2->next;
            }
    
            cur = cur->next;
        }
    
        if (l1)
        {
            cur->next = l1;
        }
        else
        {
            cur->next = l2;
        }
    
        return result->next;
    }
    

    l3的第一个节点被浪费了,可以进一步修改

    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
    {
        if (!l1 || !l2) { return l1 ? l1 : l2;}
    
        ListNode* result;
        if (l1->val < l2->val)
        {
            result = l1;
            l1 = l1->next;
        }
        else
        {
            result = l2;
            l2 = l2->next;
        }
    
        ListNode* cur = result;
        while (l1 && l2)
        {
            if (l1->val < l2->val)
            {
                cur->next = l1;
                l1 = l1->next;
            }
            else
            {
                cur->next = l2;
                l2 = l2->next;
            }
    
            cur = cur->next;
        }
    
        if (l1)
        {
            cur->next = l1;
        }
        else
        {
            cur->next = l2;
        }
    
        return result;
    }
    

    LeetCode上的最优解是用递归

    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (!l1 || !l2) return l1 ? l1 : l2;
    
        if (l1->val < l2->val) {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        }
        l2->next = mergeTwoLists(l1, l2->next);
        return l2;
    }
    
  • 相关阅读:
    toggle
    Java 运算符
    Java 修饰符
    Java 变量类型
    java对象和类
    java基础笔记
    Java添加事件的几种方式(转载了codebrother的文章)
    mybatis中的#和$的区别?
    为什么java里面经常作List判断的时候,既要判断list不为null,又要判断size>0呢,岂不是多此一举吗?
    发送邮件功能 Service 层
  • 原文地址:https://www.cnblogs.com/arcsinw/p/11264305.html
Copyright © 2020-2023  润新知