📜  合并两个未排序的链表得到一个排序的列表 – Set 2(1)

📅  最后修改于: 2023-12-03 15:22:57.631000             🧑  作者: Mango

合并两个未排序的链表得到一个排序的列表 - Set 2

在本篇文章中,我们将讨论如何合并两个未排序的链表,并将它们变成一个排序的链表。这是一个很有意义和常见的问题,特别是在面试和工作中。

问题描述

给定两个未排序的链表,合并它们并返回排序后的链表。

例如,给定以下两个链表:

l1: 1 -> 3 -> 2 -> 4 -> 5
l2: 6 -> 8 -> 7 -> 9 -> 10

我们必须将两个链表合并,并返回以下链表:

1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10
解决方法

这个问题有很多种解决方法,我们将介绍其中两种。

方法1:使用额外空间

第一种方法需要用到一个额外的数组来存储两个链表中的所有节点。然后我们可以对这个数组进行排序。最后,我们将排序后的元素重新连接成一个链表。

  • 建立一个结构体,作为链表节点的模板。
struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};
  • 将链表中的所有节点存储到一个vector中,并对其进行排序。
vector<int> nums;
ListNode* head = l1;
while (head) {
    nums.push_back(head->val);
    head = head->next;
}
head = l2;
while (head) {
    nums.push_back(head->val);
    head = head->next;
}
sort(nums.begin(), nums.end());
  • 将排序后的元素重新连接成一个链表。
ListNode* dummy = new ListNode(0);
ListNode* tail = dummy;
for (int i = 0; i < nums.size(); i++) {
    tail->next = new ListNode(nums[i]);
    tail = tail->next;
}
return dummy->next;
方法2:遍历两个链表

第二种方法是遍历两个链表,并依次比较它们的节点值。在这个过程中,我们将较小的值添加到新的链表中,同时继续遍历。当两个链表其中一个为空时,我们将另一个链表的剩余部分添加到新链表的末尾。最后返回新链表的头节点。

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    if (!l1) return l2;
    if (!l2) return l1;
    ListNode* dummy = new ListNode(0);
    ListNode* tail = dummy;
    while (l1 && l2) {
        if (l1->val < l2->val) {
            tail->next = l1;
            l1 = l1->next;
        } else {
            tail->next = l2;
            l2 = l2->next;
        }
        tail = tail->next;
    }
    if (!l1) tail->next = l2;
    if (!l2) tail->next = l1;
    return dummy->next;
}
总结

在本篇文章中,我们探讨了如何合并两个未排序的链表。我们介绍了两种不同的方法:使用额外空间和遍历两个链表。这里有一个小提示: 如果您想使用方法二,一个好的练习题目是在LeetCode上练习”Merge Two Sorted Lists”。 为了更好的理解和练习,您可以手动创建链表并尝试解决这个问题,加深对链表的理解。