leetcode 148. Sort List | 148. 排序链表(最优解归并排序,O(1)空间)
題目
https://leetcode.com/problems/sort-list/
題解
分析
就鏈表排序問題來說,它的解法可以有好多種。但它的最優(yōu)解應(yīng)該只有一種思路,即從下至上的歸并,時(shí)間復(fù)雜度 O(nlogn),空間復(fù)雜度 O(1)。詳見本文的實(shí)現(xiàn)。
另外,還有一些其他的方法,例如:
- 時(shí)間復(fù)雜度O(n^2)的 冒泡,插入
- 空間復(fù)雜度O(n)的 任意額外空間排序,最后再把鏈表重新串起來
- 時(shí)間復(fù)雜度O(nlogn),空間復(fù)雜度O(logn)的 快排
- 時(shí)間復(fù)雜度O(nlogn),空間復(fù)雜度O(logn)的從上至下 歸并
- …
最優(yōu)解(歸并)比較繞,我的辦法是多用幾個(gè)變量把中間狀態(tài)接住,兩層 while 循環(huán),外層控制 step,內(nèi)層控制每一小組內(nèi)的歸并排序,需要注意的是,內(nèi)層循環(huán)中,當(dāng)前小組的前后組都不要斷掉,所以需要記錄 preTail 和 nextHead,分別表示前一組的終點(diǎn)和后一組的起點(diǎn),方便前后的銜接。
關(guān)于本算法的時(shí)間復(fù)雜度計(jì)算,可以使用 Master 公式:
Master公式
簡介
在編程中,遞歸是非常常見的一種算法,但遞歸相比順序執(zhí)行或循環(huán)程序,時(shí)間復(fù)雜度難以計(jì)算,而master 公式就是用來計(jì)算遞歸程序的時(shí)間復(fù)雜度。
公式
T(N) = aT(N/b) + O(N^d)
- b:子過程的樣本量
- a:子過程的計(jì)算次數(shù)
- O(N^d):子結(jié)果合并的時(shí)間復(fù)雜度
滿足如上公式的程序,都可以根據(jù)master公式計(jì)算時(shí)間復(fù)雜度:
- log(b,a) > d :時(shí)間復(fù)雜度為O(N^log(b,a))
- log(b,a) = d :時(shí)間復(fù)雜度為O(N^d * logN)
- log(b,a) < d :時(shí)間復(fù)雜度為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,說明這組已經(jīng)有序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; // 和下一段接上,如果到終點(diǎn),則nextHead=null,避免了成環(huán)for (int i = 0; i < step * 2; i++) { // 更新preTailif (preTail != null) preTail = preTail.next;}p1 = nextHead;}step *= 2;}return newHead.next;} }一把過
總結(jié)
以上是生活随笔為你收集整理的leetcode 148. Sort List | 148. 排序链表(最优解归并排序,O(1)空间)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode 449. Serial
- 下一篇: leetcode 452. Minimu