leetcode 148. Sort List | 148. 排序链表(最优解归并排序,O(1)空间)
生活随笔
收集整理的這篇文章主要介紹了
leetcode 148. Sort List | 148. 排序链表(最优解归并排序,O(1)空间)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目
https://leetcode.com/problems/sort-list/
題解
分析
就鏈表排序問題來說,它的解法可以有好多種。但它的最優解應該只有一種思路,即從下至上的歸并,時間復雜度 O(nlogn),空間復雜度 O(1)。詳見本文的實現。
另外,還有一些其他的方法,例如:
- 時間復雜度O(n^2)的 冒泡,插入
- 空間復雜度O(n)的 任意額外空間排序,最后再把鏈表重新串起來
- 時間復雜度O(nlogn),空間復雜度O(logn)的 快排
- 時間復雜度O(nlogn),空間復雜度O(logn)的從上至下 歸并
- …
最優解(歸并)比較繞,我的辦法是多用幾個變量把中間狀態接住,兩層 while 循環,外層控制 step,內層控制每一小組內的歸并排序,需要注意的是,內層循環中,當前小組的前后組都不要斷掉,所以需要記錄 preTail 和 nextHead,分別表示前一組的終點和后一組的起點,方便前后的銜接。
關于本算法的時間復雜度計算,可以使用 Master 公式:
Master公式
簡介
在編程中,遞歸是非常常見的一種算法,但遞歸相比順序執行或循環程序,時間復雜度難以計算,而master 公式就是用來計算遞歸程序的時間復雜度。
公式
T(N) = aT(N/b) + O(N^d)
- b:子過程的樣本量
- a:子過程的計算次數
- O(N^d):子結果合并的時間復雜度
滿足如上公式的程序,都可以根據master公式計算時間復雜度:
- log(b,a) > d :時間復雜度為O(N^log(b,a))
- log(b,a) = d :時間復雜度為O(N^d * logN)
- log(b,a) < d :時間復雜度為O(N^d)
附草稿
代碼
/*** 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 len = 0;ListNode t = head;while (t != null) {t = t.next;len++;}int step = 1;ListNode p1;ListNode p2;ListNode preTail;ListNode nextHead;ListNode newHead = new ListNode();newHead.next = head;while (step <= len) {p1 = newHead.next;preTail = newHead;while (p1 != null) {// - - - 初始化各種位置 - - -// 找好p1,p2位置 注意超出邊界的情況p2 = p1;for (int i = 0; i < step; i++) {if (p2 != null) p2 = p2.next;}if (p2 == null) break;nextHead = p2;for (int i = 0; i < step; i++) {if (nextHead != null) nextHead = nextHead.next;}// - - - 每組排序 - - -// 如果p2=null,說明這組已經有序ListNode tp1 = p1;ListNode tp2 = p2;// 和上一段接上ListNode sortedTail = preTail;if (tp1.val < tp2.val) {preTail.next = tp1;tp1 = tp1.next;} else {preTail.next = tp2;tp2 = tp2.next;}sortedTail = sortedTail.next;while (tp1 != p2 && tp2 != nextHead) { // 歸并排序if (tp1.val < tp2.val) {sortedTail.next = tp1;tp1 = tp1.next;} else {sortedTail.next = tp2;tp2 = tp2.next;}sortedTail = sortedTail.next;}while (tp1 != p2) { // 處理剩余部分sortedTail.next = tp1;tp1 = tp1.next;sortedTail = sortedTail.next;}while (tp2 != nextHead) { // 處理剩余部分sortedTail.next = tp2;tp2 = tp2.next;sortedTail = sortedTail.next;}// - - - 排序后的處理 - - -sortedTail.next = nextHead; // 和下一段接上,如果到終點,則nextHead=null,避免了成環for (int i = 0; i < step * 2; i++) { // 更新preTailif (preTail != null) preTail = preTail.next;}p1 = nextHead;}step *= 2;}return newHead.next;} }一把過
總結
以上是生活随笔為你收集整理的leetcode 148. Sort List | 148. 排序链表(最优解归并排序,O(1)空间)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode 449. Serial
- 下一篇: leetcode 452. Minimu