对链表进行排序

111 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情

1、前言

每天一个算法小练习,本篇使用Java实现。

2、题目描述

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

  • 链表中节点的数目在范围 [0, 5 * 104] 内
  • -105 <= Node.val <= 105

2.1、示例1

image.png

输入:head = [4,2,1,3]
输出:[1,2,3,4]

2.2、示例2

image.png

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]

2.3、示例3

输入:head = []
输出:[]

3、解题思路

常用的排序算法有快排、选择、归并、插入、冒泡等,题目中进阶要求实现 O(nlogn)O(n log n) 时间复杂度和O(1)O(1)空间复杂度下排序。那么可选的就是快排、归并、堆排序。本体就非常适合使用归并排序来解决。

排序算法时间复杂度空间复杂度
冒泡排序O(n2)O(n^2)O(1)O(1)
选择排序O(n2)O(n^2)O(1)O(1)
插入排序O(n2)O(n^2)O(1)O(1)
快速排序平均O(nlogn)O(nlogn),最坏O(n2)O(n^2)O(1)O(1)
归并排序O(nlogn)O(nlogn)O(n)O(n)
堆排序O(nlogn)O(nlogn)O(1)O(1)

3.1、归并排序

归并排序就是将要排序的链表分成一个个的小链表,分而治之,再将每一排序好的小链表进行合并,得到有序链表。高效稳定,时间复杂度低。

public class Solution {

    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode p = head;
        int count = 0;
        while (p != null) {
            count++;
            p = p.next;
        }
        return sortList(head, count);
    }

    public ListNode sortList(ListNode node, int nums) { 
        ListNode resNode = new ListNode(0);
        if (node.next == null) {
            return node;
        }
        ListNode left = node, r_pre = node, right = node;
        int l_len = (nums + 1) / 2, r_len = nums- (nums + 1) / 2;
        for (int i = 1; i < l_len; i++) {
            r_pre = r_pre.next;
        }
        right = r_pre.next;
        // 二分、递归,分别排序
        r_pre.next = null; 
        left = sortList(left, l_len);
        right = sortList(right, r_len); 
        resNode.next = left;
        // p指向遍历过程中left的前一个元素
        ListNode p = resNode;
        while (left != null && right != null) {
            if (left.val > right.val) {
                r_pre = right;
                right = right.next; 
                p.next = r_pre;
                r_pre.next = left;
                p = r_pre;
            } else {
                left = left.next;
                p = p.next;
            }
        }
        if (right != null) {
            p.next = right;
        }
        return resNode.next;
    }
}

执行结果:

image.png

  • 时间复杂度:O(nlogn)O(n log n),n为链表的长度。

  • 空间复杂度:O(1)O(1)

好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊