排序連結串列(歸併排序,迭代)
阿新 • • 發佈:2021-05-23
目錄
1 題目描述
給你連結串列的頭結點 head ,請將其按 升序 排列並返回 排序後的連結串列 。
進階:
- 你可以在 O(n log n) 時間複雜度和常數級空間複雜度下,對連結串列進行排序嗎?
示例 1:
輸入:head = [4,2,1,3]
輸出:[1,2,3,4]
示例 2:
輸入:head = [-1,5,3,4,0]
輸出:[-1,0,3,4,5]
示例 3:
輸入:head = []
輸出:[]
提示:
- 連結串列中節點的數目在範圍 [0, 5 * 10 ^ 4] 內
- -10 ^ 5 <= Node.val <= 10 ^ 5
2 解題(Java)
題目解析
- 最適合連結串列的排序演算法是歸併排序。如果採用自頂向下的遞迴實現,則空間複雜度為O(log n),如果要達到O(1)的空間複雜度,則需要使用自底向上的實現方式;
- 首先求得連結串列的長度length,然後將連結串列拆分成子連結串列進行合併;
- 用subLength表示每次需要排序的子連結串列的長度,初始subLength=1;
- 每次將連結串列拆分成若干個長度為subLength的子連結串列(最後一個子連結串列的長度可以小於subLength),按照每兩個子連結串列一組進行合併,合併後即可得到若干個長度為subLength * 2的有序子連結串列(最後一個子連結串列的長度可以小於subLength * 2);
- 將subLength的值加倍,重複4,對更長的有序子連結串列進行合併操作,直到有序子連結串列的長度大於或等於length,整個連結串列排序完畢;
程式碼
/**
* 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) {
int length = 0;
ListNode node = head;
while (node != null) {
node = node.next;
length++;
}
ListNode dummyHead = new ListNode(0, head);
for (int subLength = 1; subLength < length; subLength <<= 1) {
ListNode prev = dummyHead, curr = dummyHead.next;
while (curr != null) {
ListNode head1 = curr;
for (int i=1; i<subLength && curr.next != null; i++) {
curr = curr.next;
}
ListNode head2 = curr.next;
curr.next = null;
curr = head2;
for (int i = 1; i < subLength && curr != null && curr.next != null; i++) {
curr = curr.next;
}
ListNode next = null;
if (curr != null) {
next = curr.next;
curr.next = null;
}
ListNode merged = merge(head1, head2);
prev.next = merged;
while (prev.next != null) {
prev = prev.next;
}
curr = next;
}
}
return dummyHead.next;
}
public ListNode merge(ListNode head1, ListNode head2) {
ListNode dummyHead = new ListNode();
ListNode temp = dummyHead;
while (head1 != null && head2 != null) {
if (head1.val <= head2.val) {
temp.next = head1;
head1 = head1.next;
} else {
temp.next = head2;
head2 = head2.next;
}
temp = temp.next;
}
temp.next = head1 == null ? head2 : head1;
return dummyHead.next;
}
}
3 複雜性分析
- 時間複雜度O(nlogn):其中 n 是連結串列的長度;
- 空間複雜度O(1)
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/sort-list