【LeetCode刷題筆記(七十二)】之148 排序連結串列
阿新 • • 發佈:2021-01-16
本文章由公號【開發小鴿】釋出!歡迎關注!!!
老規矩–妹妹鎮樓:
一. 題目
(一) 題幹
給你連結串列的頭結點 head ,請將其按 升序 排列並返回 排序後的連結串列 。
進階:
你可以在 O(n log n) 時間複雜度和常數級空間複雜度下,對連結串列進行排序嗎?
(二) 示例
輸入:head = [4,2,1,3]
輸出:[1,2,3,4]
二. 題解
(一) 思路
之前我們使用插入排序對連結串列進行了排序,時間複雜度為O(n2),這裡我們使用歸併排序進行優化,將時間複雜度降低到O(nlogn)。歸併排序需要找到連結串列的中間節點,中間節點通過快慢指標來獲取,然後對兩邊的連結串列分別進行遞迴歸併排序,將兩個排好序的連結串列再整合起來,整合的過程就是簡單的判斷大小,將小的節點新增到新的連結串列中。
(二) 程式碼
Java:
/**
* 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) {
// 歸併排序
// 尾部是null
return sortList(head, null);
}
public ListNode sortList(ListNode head, ListNode tail){
if(head == null){
return head;
}
if(head.next == tail){
head.next = null;
return head;
}
// 找到中間節點
ListNode low = head, fast = head;
while(fast != tail){
fast = fast.next;
low = low.next;
if(fast != tail){
fast = fast.next;
}
}
ListNode mid = low;
ListNode s1 = sortList(head, mid);
ListNode s2 = sortList(mid, tail);
// 歸併兩個佇列
ListNode sorted = merge(s1, s2);
return sorted;
}
// 正常的歸併演算法
public ListNode merge(ListNode head1, ListNode head2){
ListNode dumHead = new ListNode(0);
ListNode temp = dumHead, temp1 = head1, temp2 = head2;
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 dumHead.next;
}
}