1. 程式人生 > 實用技巧 >連結串列 21.合併兩個有序連結串列

連結串列 21.合併兩個有序連結串列

題目

將兩個升序連結串列合併為一個新的升序連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。

輸入:1->2->4, 1->3->4

輸出:1->1->2->3->4->4

題目來源

思路

第一個思路就是以迭代的方式,逐一比較連結串列元素大小關係,改變指標的指向,最後整合成一條有序的連結串列,這個思路比較簡單。另外一個思路需要理解理解,用遞迴的方式。在寫程式碼前,先想一想遞迴的公式。

result = L1+mergeTwoLists(L1->next,L2) L1->val < L2->val

result = L2+mergeTwoLists(L1,L2->next) 其他(L1->val >= L2->val)

當L1的元素小於L2的元素時,合併的新連結串列 = L1當前節點 + L1剩餘連結串列與L2連結串列的合併。反之則是,合併的新連結串列 = L2當前節點 + L2剩餘連結串列與L1連結串列的合併。

因為合併的過程存在重複的操作,所以才使用遞迴。

遞迴出口為

if(!L1) { return L2; } if(!L2) { return L1; }

即當L1為空,則合併連結串列為L2,當L2為空,則合併連結串列為L1。

程式碼實現

/**

*迭代

*/

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(!l1)
    {
        return l2;
    }
    if(!l2)
    {
        return l1;
    }
    
    struct
ListNode *head = (struct ListNode*)malloc(sizeof(struct ListNode)); struct ListNode *p = head; while( l1 != NULL && l2 != NULL ) { if( l1->val < l2->val ) { p->next = l1; l1 = l1->next; } else { p->next = l2; l2 = l2->next; } p = p->next; } /* *接上已經有序的部分連結串列 */ if (l1) p->next = l1; else if (l2) p->next = l2; return head->next; }

/**

*遞迴

*/

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(!l1)
    {
        return l2;
    }
    if(!l2)
    {
        return l1;
    }
    
    if( l1->val < l2->val )
    {
        l1->next = mergeTwoLists(l1->next,l2);
        return l1;
    }
    else
    {
        l2->next = mergeTwoLists(l1,l2->next);
        return l2;
    }
}