【LeetCode】 排序链表

79 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第23天,点击查看活动详情

排序链表

原题:leetcode-cn.com/problems/so…

描述

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

难度

中等

示例

输入: 4->2->1->3
输出: 1->2->3->4
输入: -1->5->3->4->0
输出: -1->0->3->4->5

思路

为了使时间复杂度达到 O(n log n),我们使用归并排序对链表进行排序,归并排序使用的是分治的思想。首先对链表进行分解,以中间节点分割,左边一半,右边一半,然后对左右两边继续进行分解,将左边分解后得到的有序链表和右边分解后得到的有序链表进行合并得到一个新的有序的链表,然后返回。

定义函数 sort(head, tail) 用来分解链表, 函数 merge(head1, head2) 用来合并两个有序链表并返回一个新的链表,在 sort() 函数中,需要将链表拆成两半,此时需要一个获取中间节点的函数 getMiddleNode(head, tail) ,这里使用快慢指针来实现查找链表的中间节点,然后分别对拆开后的链表进行分解排序。

代码

Rust

#[derive(PartialEq, Eq, Clone, code_rust_macro::ListNodeDebug)]
pub struct ListNode {
    pub val: i32,
    pub next: Option<Box<ListNode>>
}
​
impl ListNode {
    #[inline]
    fn new(val: i32) -> Self {
        ListNode { next: None, val }
    }
}
​
pub struct Solution {}
​
impl Solution {
    pub fn sort_list(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        let len = Solution::get_len(&head);
        Solution::sort(head, len)
    }
​
    /// 分解排序
    fn sort(mut head: Option<Box<ListNode>>, len: usize) -> Option<Box<ListNode>> {
        if head.is_none() || head.as_ref().unwrap().next.is_none() {
            return head;
        }
        let middle = len >> 1;
        let mut middle_node = &mut head;
        for _ in 0..middle {
            middle_node = &mut middle_node.as_mut().unwrap().next;
        }
        // 断开链表
        let middle_node = middle_node.take();
​
        // 分解左边
        let head1 = Solution::sort(head, middle);
        // 分解右边
        let head2 = Solution::sort(middle_node, len - middle);
        // 将两个有序的链表合并成一个链表
        Solution::merge(head1, head2)
    }
​
    /// 合并有序链表
    fn merge(
        l1: Option<Box<ListNode>>,
        l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        let mut new_list_node = Some(Box::new(ListNode::new(0)));
        let mut prev_new_node = &mut new_list_node;
        let (mut node1, mut node2) = (&l1, &l2);
        while node1.is_some() && node2.is_some() {
            let node_box1 = node1.as_ref().unwrap();
            let node_box2 = node2.as_ref().unwrap();
            // 判断左边链表节点是否小于等于右边链表节点
            if node_box1.val <= node_box2.val {
                // 将下一个节点添加到上一个节点的后面
                prev_new_node.as_mut().unwrap().next =
                    Some(Box::new(ListNode::new(node_box1.val)));
                // 左边当前链表节点后移
                node1 = &node_box1.next;
            } else {
                // 判断左边链表节点是大于右边链表节点
                // 将下一个节点添加到上一个节点的后面
                prev_new_node.as_mut().unwrap().next =
                    Some(Box::new(ListNode::new(node_box2.val)));
                // 右边当前链表节点后移
                node2 = &node_box2.next;
            }
            // 记录上一个节点
            prev_new_node = &mut prev_new_node.as_mut().unwrap().next;
        }
​
        // 左边链表还有剩余节点,直接添加到末尾
        if node1.is_some() {
            prev_new_node.as_mut().unwrap().next = node1.clone()
        }
        // 右边链表还有剩余节点,直接添加到末尾
        if node2.is_some() {
            prev_new_node.as_mut().unwrap().next = node2.clone();
        }
​
        new_list_node.take().unwrap().next
    }
​
    fn get_len(head: &Option<Box<ListNode>>) -> usize {
        let mut len = 0;
        let mut current = head;
        while let Some(node) = current.as_ref() {
            current = &node.next;
            len += 1
        }
        len
    }
}
#[test]
fn test_sort_list() {
    let mut node1 = Some(Box::new(ListNode::new(4)));
    let mut node2 = Some(Box::new(ListNode::new(2)));
    let mut node3 = Some(Box::new(ListNode::new(1)));
    let node4 = Some(Box::new(ListNode::new(3)));
​
    node3.as_mut().unwrap().next = node4;
    node2.as_mut().unwrap().next = node3;
    node1.as_mut().unwrap().next = node2;
​
    println!("{:?}", node1);
​
    let node = Solution::sort_list(node1);
​
    println!("{:?}", node);
​
    let mut node1 = Some(Box::new(ListNode::new(-1)));
    let mut node2 = Some(Box::new(ListNode::new(5)));
    let mut node3 = Some(Box::new(ListNode::new(3)));
    let mut node4 = Some(Box::new(ListNode::new(4)));
    let node5 = Some(Box::new(ListNode::new(0)));
​
    node4.as_mut().unwrap().next = node5;
    node3.as_mut().unwrap().next = node4;
    node2.as_mut().unwrap().next = node3;
    node1.as_mut().unwrap().next = node2;
​
    println!("{:?}", node1);
​
    let node = Solution::sort_list(node1);
​
    println!("{:?}", node);
}

运行结果:

Some(4->2->1->3)
Some(1->2->3->4)
Some(-1->5->3->4->0)
Some(-1->0->3->4->5)

Go

type ListNode struct {
    Val int
    Next *ListNode
}
​
func sortList(head *ListNode) *ListNode {
    return sort(head, nil)
}
​
// 分解排序
func sort(head, tail *ListNode) *ListNode {
    if head == tail {
        return head
    }
    middleNode := getMiddleNode(head, tail)
    // 保存下一个节点
    next := middleNode.Next
    // 断开链表
    middleNode.Next = nil
    // 分解左边
    head1 := sort(head, middleNode)
    // 分解右边
    head2 := sort(next, tail)
    // 将两个有序的链表合并成一个链表
    return merge(head1, head2)
}
​
// 合并有序链表
func merge(head1, head2 *ListNode) *ListNode {
    current1, current2 := head1, head2
​
    var appendNode *ListNode
    newHead := &ListNode{Val: -1}
    last := newHead
    for current1 != nil && current2 != nil {
        if current1.Val <= current2.Val {
            appendNode = current1
            current1 = current1.Next
        } else {
            appendNode = current2
            current2 = current2.Next
        }
        last.Next = appendNode
        last = appendNode
    }
​
    // 左边还有剩余节点
    if current1 != nil {
        last.Next = current1
    }
    // 右边还有剩余节点
    if current2 != nil {
        last.Next = current2
    }
​
    return newHead.Next
}
​
// 获取链表的中间节点
func getMiddleNode(head, tail *ListNode) *ListNode {
    fast, slow := head, head
    for fast != tail && fast.Next != tail {
        fast = fast.Next.Next
        slow = slow.Next
    }
    return slow
}
​
func printListNode(node *ListNode) {
    var str = ""
    for node != nil {
        str += fmt.Sprintf("%d->", node.Val)
        node = node.Next
    }
    str = strings.TrimSuffix(str, "->")
    fmt.Println(str)
}
func TestSortList(t *testing.T) {
    node1 := &ListNode{Val: 4}
    node2 := &ListNode{Val: 2}
    node3 := &ListNode{Val: 1}
    node4 := &ListNode{Val: 3}
    node1.Next = node2
    node2.Next = node3
    node3.Next = node4
​
    printListNode(node1)
​
    node := sortList(node1)
​
    printListNode(node)
​
    node1 = &ListNode{Val: -1}
    node2 = &ListNode{Val: 5}
    node3 = &ListNode{Val: 3}
    node4 = &ListNode{Val: 4}
    node5 := &ListNode{Val: 0}
    node1.Next = node2
    node2.Next = node3
    node3.Next = node4
    node4.Next = node5
​
    printListNode(node1)
​
    node = sortList(node1)
​
    printListNode(node)
}

运行结果:

4->2->1->3
1->2->3->4
-1->5->3->4->0
-1->0->3->4->5

Java

public class Main {
​
    public static class ListNode {
        public int val;
        public ListNode next;
        public ListNode(int val) {
            this.val = val;
        }
    }
​
    public static ListNode sortList(ListNode head) {
        return sort(head, null);
    }
​
    public static ListNode sort(ListNode head, ListNode tail) {
        if (head == tail) {
            return head;
        }
        ListNode middleNode = getMiddleNode(head, tail);
        // 保存下一个节点
        ListNode next = middleNode.next;
        // 断开链表
        middleNode.next = null;
        // 分解左边
        ListNode head1 = sort(head, middleNode);
        // 分解右边
        ListNode head2 = sort(next, tail);
        // 将两个有序的链表合并成一个链表
        return merge(head1, head2);
    }
​
    /**
     * 合并有序链表
     */
    public static ListNode merge(ListNode head1, ListNode head2) {
        ListNode current1 = head1, current2 = head2;
        ListNode appendNode = null;
        ListNode newHead = new ListNode(-1);
        ListNode last = newHead;
        while (current1 != null && current2 != null) {
            if (current1.val <= current2.val) {
                appendNode = current1;
                current1 = current1.next;
            } else {
                appendNode = current2;
                current2 = current2.next;
            }
            last.next = appendNode;
            last = appendNode;
        }
​
        // 左边还有剩余节点
        if (current1 != null) {
            last.next = current1;
        }
        // 右边还有剩余节点
        if (current2 != null) {
            last.next = current2;
        }
​
        return newHead.next;
    }
​
    /**
     * 获取链表的中间节点
     */
    public static ListNode getMiddleNode(ListNode head, ListNode tail) {
        ListNode fast = head, slow = head;
        while (fast != tail && fast.next != tail) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
​
    private static void printListNode(ListNode node) {
        StringBuilder sb = new StringBuilder();
        while (node != null) {
            sb.append(node.val).append("->");
            node = node.next;
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.deleteCharAt(sb.length() - 1);
        System.out.println(sb.toString());
    }
​
    public static void main(String[] args) {
        ListNode node1 = new ListNode(4);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(1);
        ListNode node4 = new ListNode(3);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
​
        printListNode(node1);
​
        ListNode node = sortList(node1);
​
        printListNode(node);
​
        node1 = new ListNode(-1);
        node2 = new ListNode(5);
        node3 = new ListNode(3);
        node4 = new ListNode(4);
        ListNode node5 = new ListNode(0);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
​
        printListNode(node1);
​
        node = sortList(node1);
​
        printListNode(node);
    }
}

运行结果:

4->2->1->3
1->2->3->4
-1->5->3->4->0
-1->0->3->4->5