LeetCode热题100--148. 排序链表--中等
1.题目
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
示例 1:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2:
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例 3:
输入:head = []
输出:[]
2. 题解
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode sortList(ListNode head) {//如果链表为空或者只有一个节点,无需排序if (head == null || head.next == null){return head;}// 找到中间节点head2,并断开head2与其前一个节点的连接//比如head=[4,2,1,3],那么middleNode调用结束后head=[4,2],head=[1,3]ListNode head2 = middleNode(head);//分治head = sortList(head);head2 = sortList(head2);//合并return mergeTwoLists(head,head2);}// 876. 链表的中间结点(快慢指针)private ListNode middleNode(ListNode head){ListNode pre = head;ListNode slow = head;ListNode fast = head;while( fast != null && fast.next != null){pre = slow; //记录slow的前一个节点slow = slow.next;fast = fast.next.next;}pre.next = null; //断开slow的前一个节点和slow的连接return slow;}// 21. 合并两个有序链表(双指针)private ListNode mergeTwoLists(ListNode list1,ListNode list2){ListNode dummy = new ListNode(); //用哨兵节点简化代码逻辑ListNode cur = dummy; //cur 指向新链表的末尾while(list1 != null && list2 != null){if(list1.val < list2.val){cur.next = list1; //把list1加到新链表中list1 = list1.next;} else { // 注:相等的情况加哪个节点都是可以的cur.next = list2; // 把list2加到新链表中list2 = list2.next;}cur = cur.next;}cur.next = list1 != null ? list1 : list2; // 拼接剩余链表return dummy.next;}
}
3. 解析
出自这位老师:灵茶山艾府:两种方法:分治/迭代,模块化设计,代码可读性高(Python/Java/C++/C/Go/JS/Rust)
-
private ListNode middleNode(ListNode head): 这个方法使用了快慢指针的方法来找出链表的中间节点。如果链表有奇数个节点,slow指针会停在最后一个节点;如果是偶数个节点,slow指针会停在第二个中间节点。为了方便后续操作(断开链表的连接),我们需要记录慢指针的前驱节点。
-
private ListNode mergeTwoLists(ListNode list1,ListNode list2): 这个方法通过创建一个新的哨兵节点和两个输入链表一起进行比较来合并两个有序链表。它会持续地选择较小的值,并在新链表中添加。当其中一个链表耗尽时,它将自动拼接剩余的另一个链表到结果中。
-
public ListNode sortList(ListNode head): 这个方法首先检查给定的链表是否为空或者只有一个节点(这意味着已经是有序的)。如果不是,则找到中间节点并断开连接,然后递归地对两半部分进行排序,最后将结果合并起来。