龙空技术网

算法之排序链表

无涯子Z 80

前言:

如今你们对“java排序链表”大概比较着重,同学们都需要分析一些“java排序链表”的相关内容。那么小编在网摘上搜集了一些关于“java排序链表””的相关文章,希望兄弟们能喜欢,大家快快来了解一下吧!

题目描述:

leetcode 148 排序链表

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

解题思路:

思路:归并排序对于链表排序来说是一种非常有效和稳定的方法。

解题思路:

分解:首先,将链表一直对半分割,直到链表只剩下一个或两个节点。这是递归的基础情况。递归解决:对于每个子链表,递归地应用归并排序。这意味着对每个子链表继续分解,直到达到基础情况,然后合并它们。合并:合并两个已排序的子链表。这是归并排序的关键步骤。你需要创建一个新链表,然后比较两个子链表的头节点,将较小的节点添加到新链表中,移动相应链表的头指针。重复此过程,直到一个链表为空,然后将另一个链表的剩余部分添加到新链表的末尾。代码实现

public class SortList {        public ListNode sortList(ListNode head) {        return sortList(head, null);    }    /**     * 递归将链表对半分割,直到只剩下一个或两个节点     * @param head     * @param tail     */    public ListNode sortList(ListNode head, ListNode tail) {        // 链表为空直接返回        if(head == null) {            return head;        }        // 只有两个节点的链表,调整顺序返回        if(head.next == tail) { //??            head.next = null;            return head;        }        // 使用快慢指针找到中间节点        ListNode slow = head, fast = head;        while(fast != tail) {            slow = slow.next;            fast = fast.next;            if(fast != tail) {                fast = fast.next;            }        }        ListNode mid = slow;        // 递归对左右两部分进行排序        ListNode list1 = sortList(head, mid);        ListNode list2 = sortList(mid, tail);        // 合并已排序的链表        ListNode sorted = merge(list1, list2);        return sorted;    }    public ListNode merge(ListNode l1, ListNode l2) {        ListNode dummy = new ListNode(0);        ListNode temp = dummy, temp1 = l1, temp2 = l2;        // 链表都不为空时合并链表        while(temp1 != null && temp2 != null) {            if(temp1.val <= temp2.val) {                temp.next = temp1;                temp1 = temp1.next;            } else {                temp.next = temp2;                temp2 = temp2.next;            }            temp = temp.next;        }        // 两链表其中一个为空时,直接将另外一个链表连接到新链表的末尾        if(temp1 != null) {            temp.next = temp1;        } else if(temp2 != null) {            temp.next = temp2;        }        return dummy.next;    }}

时间复杂度分析链表对半分割:使用快慢指针法找到链表的中点,时间复杂度为O(n),其中n为链表的长度。子链表的递归排序:每次将链表一分为二,递归调用自身进行排序。最坏情况下(完全逆序),整个过程类似二叉树的完全分解,深度为log_2(n),每层需要进行一次O(n)的分割操作,因此这部分的时间复杂度为O(n log n)。有序子链表的合并:假设已有merge方法能将两个有序链表合并成一个有序链表,且时间复杂度为O(m + n),其中m和n分别为两个链表的长度。在本问题中,每次合并的是两个大小大致相等的子链表,所以合并操作的时间复杂度可以视为O(n)。易错点合并链表时,两个链表为空的情况利用快慢指针找到中间节点的方法。

标签: #java排序链表