合并无序链表(百度面试)

题目描述(Easy)

合并两个无序链表成为有序链表

https://leetcode.com/problems/insertion-sort-list/submissions/

https://leetcode.com/problems/sort-list/submissions/

https://leetcode.com/problems/merge-two-sorted-lists/submissions/

算法分析

先排序,再合并。

插入排序:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* insertionSortList(ListNode* head) {
        if (!head) return head;
        ListNode* fake = new ListNode(-1);        
        ListNode *p1 = head;
        
        while(p1) {     
            ListNode *p2 = p1, *p3 = fake;
            p1 = p1->next;
            while (p3->next != nullptr && p2->val > p3->next->val) {
                p3 = p3->next;
            }
            
            p2->next = p3->next;
            p3->next = p2;
        }
        
        return fake->next;
    }
};

归并排序:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if (!head || !head->next) return head;
        
        // 找到中间节点
        ListNode* fast = head, *slow = head;
        while (fast->next && fast->next->next) {
            fast = fast->next->next;
            slow = slow->next;
        }
        
        // 中间断开
        fast = slow->next;
        slow->next = nullptr;
        
        ListNode* head1 = sortList(fast);
        ListNode* head2 = sortList(head);
        
        return mergeList(head1, head2);
    }
    
    
    ListNode* mergeList(ListNode* head1, ListNode* head2) {
        ListNode* dummy = new ListNode(-1);
        ListNode* temp = dummy;
        while (head1 && head2) {
            if (head1->val < head2->val)
            {
                temp->next = head1;
                head1 = head1->next;
            } else {
                temp->next = head2;
                head2 = head2->next;
            }
            temp = temp->next;
        }
        
        if (head1) {
            temp->next = head1;
        }
        if (head2) {
            temp->next = head2;
        }
        return dummy->next;
    }

};

调用stl排序:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
    
bool nodeListCmp(ListNode* l1, ListNode* l2) {
    return l1->val < l2->val;
}

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if (!head) return head;
        vector<ListNode*> nodeList;
        
        while(head) {
            nodeList.push_back(head);
            head = head->next;
        }
        
        sort(nodeList.begin(), nodeList.end(), nodeListCmp);
        ListNode* newHead = nodeList[0], *temp = newHead;
        
        for (int i = 1; i < nodeList.size(); ++i) {
            temp->next = nodeList[i];
            temp = temp->next;
        }
        temp->next = nullptr;
        
        return newHead;
    }

};

合并链表:

/**
 * 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) {
        if (!l1) return l2;
        if (!l2) return l1;
        
        ListNode* fake = new ListNode(-1);
        ListNode* cur = fake;
        
        while (l1 && l2) {
            if (l1->val < l2->val) {
                cur->next = l1;
                l1 = l1->next;
            } else {
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }
        
        while (l1) {
            cur->next = l1;
            l1 = l1->next;
            cur = cur->next;
        }
        
        while (l2) {
            cur->next = l2;
            l2 = l2->next;
            cur = cur->next;
        }
        
        return fake->next;
    }
};

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C语言合并两个无序链表的示例代码: ```c #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next; } Node; Node* createList(int arr[], int n) { Node *head = NULL, *tail = NULL; for (int i = 0; i < n; i++) { Node *newNode = (Node*) malloc(sizeof(Node)); newNode->data = arr[i]; newNode->next = NULL; if (tail == NULL) { head = tail = newNode; } else { tail->next = newNode; tail = newNode; } } return head; } void printList(Node *head) { while (head != NULL) { printf("%d ", head->data); head = head->next; } printf("\n"); } Node* mergeLists(Node *head1, Node *head2) { if (head1 == NULL) { return head2; } if (head2 == NULL) { return head1; } Node *ptr1 = head1, *ptr2 = head2; Node *head = NULL, *tail = NULL; while (ptr1 != NULL && ptr2 != NULL) { Node *newNode = (Node*) malloc(sizeof(Node)); if (ptr1->data <= ptr2->data) { newNode->data = ptr1->data; ptr1 = ptr1->next; } else { newNode->data = ptr2->data; ptr2 = ptr2->next; } newNode->next = NULL; if (tail == NULL) { head = tail = newNode; } else { tail->next = newNode; tail = newNode; } } if (ptr1 != NULL) { tail->next = ptr1; } if (ptr2 != NULL) { tail->next = ptr2; } return head; } int main() { int arr1[] = {3, 1, 4, 5, 2}; int arr2[] = {9, 6, 7, 8}; Node *head1 = createList(arr1, 5); Node *head2 = createList(arr2, 4); printf("List 1: "); printList(head1); printf("List 2: "); printList(head2); Node *head = mergeLists(head1, head2); printf("Merged List: "); printList(head); return 0; } ``` 在上面的代码中,我们定义了一个`Node`结构体来表示链表的节点,其中包含一个整数数据和一个指向下一个节点的指针。我们还定义了`createList`函数来创建链表,`printList`函数来打印链表,以及`mergeLists`函数来合并两个链表。 `mergeLists`函数使用两个指针`ptr1`和`ptr2`分别遍历两个链表,并将它们的节点逐个比较,将较小的节点添加到新链表中。最后,将任何剩余的节点添加到新链表的末尾,并返回新链表的头指针。 在`main`函数中,我们创建了两个无序链表,打印它们,然后将它们合并并打印结果链表。运行程序将输出以下内容: ``` List 1: 3 1 4 5 2 List 2: 9 6 7 8 Merged List: 1 2 3 4 5 6 7 8 9 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值