力扣热题100 - 链表:排序链表

题目描述:

题号:148

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

图片

 

解题思路:

思路一:归并排序

1、找到中间节点(可以利用前面链表题中的函数)

2、分割链表:首先检查链表是否为空或只有一个节点,如果是,则直接返回该链表,因为无需排序。

然后,将链表从中间分成两部分。分割是通过将中间节点的 next 指针设为 nullptr 来实现的,从而得到两个独立的子链表。

3、递归排序子链表:对分割后的两个子链表(左子链表和右子链表)分别递归调用 sortList 函数进行排序。

这是归并排序算法的核心步骤之一,将大问题分解为小问题。

4、有序合并排序后的链表

时间复杂度:O(N logN)

空间复杂度:O(logN)

C++

// C++
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    ListNode* midList(ListNode* head) {
        if(head == nullptr || head->next == nullptr) {
            return head;
        }
        ListNode *fast = head;
        ListNode *slow = head;
        while(fast->next != nullptr && fast->next->next != nullptr) {
            fast = fast->next->next;
            slow = slow->next;
        }
        return slow;
    }

    ListNode* mergeList(ListNode* head1, ListNode* head2) {
        if(head1 == nullptr && head2 == nullptr) {
            return nullptr;
        }
        unique_ptr<ListNode> dummyHead (new ListNode(99999));
        ListNode* cur = dummyHead.get();
        while(head1 != nullptr && head2 != nullptr) {
            if(head1->val <= head2->val) {
                cur->next = head1;
                head1 = head1->next;
                
            } else {
                cur->next = head2;
                head2 = head2->next;
                
            }
            cur = cur->next;
        }

        if(head1 != nullptr || head2 != nullptr) {
            cur->next = head1 == nullptr ? head2 : head1;
        }
        return dummyHead->next;
    }
public:
    ListNode* sortList(ListNode* head) {
        if(head == nullptr || head->next == nullptr) {
            return head;
        }
        // chaifen
        ListNode *mid = midList(head);
        ListNode *left = head;
        ListNode *right = mid->next;
        mid->next = nullptr;

        // liangbiandigui
        ListNode *lHead = sortList(left);
        ListNode *rHead = sortList(right);

        // hebing
        ListNode *newHead = mergeList(lHead, rHead);

        return newHead;
    }
};

go


// go
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func sortList(head *ListNode) *ListNode {
    // 递归结束条件
    if head == nil || head.Next == nil {
        return head
    }

    // 先找到中间节点
    mid := middleNode(head)

    // 拆分左右两个链条
    left := head
    right := mid.Next
    mid.Next = nil

    // 两边递归排序
    lHead := sortList(left)
    rHead := sortList(right)

    // 合并有序链表
    mergeHead := mergeTwoLists(lHead, rHead)

    return mergeHead
}

// 返回链表中间节点,如果节点个数是偶数,则返回第一个中间节点
func middleNode(head *ListNode) *ListNode {
    if head == nil || head.Next == nil {
        return head
    }

    slow := head
    fast := head

    for fast.Next != nil && fast.Next.Next != nil {
        fast = fast.Next.Next
        slow = slow.Next
    }

    return slow
}

// 合并两个有序的链表
func mergeTwoLists(list1, list2 *ListNode) *ListNode {
    list3 := &ListNode{-1, nil}
    temp := list3

    for list1 != nil && list2 != nil {
        if list1.Val <= list2.Val {
            temp.Next = list1
            list1 = list1.Next
        } else {
            temp.Next = list2
            list2 = list2.Next
        }
        temp = temp.Next
    }

    if list1 == nil {
        temp.Next = list2
    } else {
        temp.Next = list1
    }

    return list3.Next
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值