zoukankan      html  css  js  c++  java
  • 【LeetCode & 剑指offer刷题】链表题7:25 合并两个排序的链表(系列)(21. Merge Two Sorted Lists)

    【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

    21. Merge Two Sorted Lists

    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
     
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    /*
    联系合并两个排序的数组,temp[k++] = (a[i]<b[j])? a[i++] : b[j++]
    */
    class Solution
    {
    public:
        ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
        {
            if(l1 == nullptr) return l2;
            if(l2 == nullptr) return l1;
           
            ListNode prehead(0); //头结点前面附加一结点(当原链表头结点可能会变化时都可以考虑使用prehead
            ListNode* p = &prehead; //新链表结点指针
            for(; l1!=nullptr && l2!=nullptr; p = p->next) //比较l1和l2各结点大小,归并
            {
                if(l1->val < l2->val)
                {
                    p->next = l1; //下一个结点指向l1结点
                    l1 = l1->next;
                }
                else
                {
                    p->next = l2;
                    l2 = l2->next;
                }
            }
           
            if(l1!=nullptr) p->next = l1; //处理剩余结点
            if(l2!=nullptr) p->next = l2;
            return prehead.next; //返回头结点指针
        }
    };
     
    23. Merge k Sorted Lists (hard)
    Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
    Example:
    Input:
    [
    1->4->5,
    1->3->4,
    2->6
    ]
    Output: 1->1->2->3->4->4->5->6
     
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    //多次用merge2lists的方法
    class Solution
    {
    public:
        ListNode* mergeKLists(vector<ListNode*>& lists)
        {
            if(lists.empty()) return nullptr;
           
         /*   ListNode* p = lists[0]; //初始化为第一个链表头指针
            for(int i = 1; i<lists.size(); i++) //归并次数为lists.size()
            {
                p = mergeTwoLists(p, lists[i]);
            }
            return p;*/ //很耗时
    /*
    例:
    len=5,list[0],list[1],list[2],list[3],list[4]
    len/2 = 5/2 = 2;
    i=0, (0,4)
    i=1, (1,3)
    (len+1)/2 = 3,保留 list[0],list[1],list[2],新len=3
     
    */   
            while (lists.size() > 1)
            {
                int len = lists.size(); //当前链表数量
                for (int i = 0; i < len/2; i++) //改进为不断二分归并,归并次数可以减少为n/2 + n/4 + ... +1
                {
                    lists[i] = mergeTwoLists(lists[i], lists[len - i - 1]); //首尾对应归并
                }
                lists.resize((len + 1)/2); //新链表数量
            }
            return lists[0];
           
        }
    private:
        ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
        {
            if(l1 == nullptr) return l2;//可加上特殊情况:如果l1=l2,直接返回l1
            if(l2 == nullptr) return l1;
           
            ListNode prehead(0); //头结点前面附加一结点
            ListNode* p = &prehead; //新链表结点指针
            for(; l1!=nullptr && l2!=nullptr; p = p->next) //比较l1和l2各结点大小,归并
            {
                if(l1->val < l2->val)
                {
                    p->next = l1; //下一个结点指向l1结点
                    l1 = l1->next;
                }
                else
                {
                    p->next = l2;
                    l2 = l2->next;
                }
            }
           
            if(l1!=nullptr) p->next = l1; //处理剩余结点
            if(l2!=nullptr) p->next = l2;
            return prehead.next; //返回头结点指针
        }
    };
     
    Sort List
    Sort a linked list in O(n log n) time using constant space complexity.
    Example 1:
    Input: 4->2->1->3
    Output: 1->2->3->4
    Example 2:
    Input: -1->5->3->4->0
    Output: -1->0->3->4->5

    C+
     
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    /*
    问题:对链表排序
    方法:归并排序
    先用快慢指针法找到链表中部位置,对左右子链表递归处理,进行分割和归并
    O(nlogn) O(1)
    */
    class Solution
    {
    public:
        ListNode* sortList(ListNode* head)
        {
            if (!head || !head->next) return head;
           
            ListNode *slow = head, *fast = head, *pre = head;
            while (fast && fast->next)
            {
                pre = slow;
                slow = slow->next;
                fast = fast->next->next;
            }//退出循环时,fast或fast->next = nullptr,slow指向中部位置
            pre->next = NULL; //将左右子链表断开处理
           
            return merge(sortList(head), sortList(slow)); //归并左右子链表     
        }
       
        ListNode* merge(ListNode* l1, ListNode* l2)
        {
            if(l1 == nullptr) return l2;
            if(l2 == nullptr) return l1;
          
            ListNode prehead(0); //头结点前面附加一结点(当原链表头结点可能会变化时都可以考虑使用prehead
            ListNode* p = &prehead; //新链表结点指针
            for(; l1!=nullptr && l2!=nullptr; p = p->next) //比较l1l2各结点大小,归并
            {
                if(l1->val < l2->val)
                {
                    p->next = l1; //下一个结点指向l1结点
                    l1 = l1->next;
                }
                else
                {
                    p->next = l2;
                    l2 = l2->next;
                }
            }
          
            if(l1!=nullptr) p->next = l1; //处理剩余结点
            if(l2!=nullptr) p->next = l2;
            return prehead.next; //返回头结点指针
        }
    };
     
  • 相关阅读:
    springboot + driud连接池踩的坑____新手学习
    tomcat的安装
    无限极分类
    javascript ECMAscript 和node.js commonJs之间的关系
    变量名,引用和地址
    java中闭包的理解
    thinkphp 模型的curd
    thinkphp之migration 迁移文件的使用
    验证ArrayList是线程不安全的集合
    一个java小程序,盗取插入的U盘中的数据。
  • 原文地址:https://www.cnblogs.com/wikiwen/p/10225210.html
Copyright © 2011-2022 走看看