給你鍊錶的頭結點節點結構head
,請將其按公升序排列並返回排序後的鍊錶。例如:4->2->1->3
排序 1->2->3->4
要求時間複雜度o(nlongn) 空間複雜度 o(1)
public class listnode
listnode(int val)
listnode(int val, listnode next)
}
歸併排序的含義 將兩個或者兩個以上的有序表組合成乙個新的有序表
該題使用的是二路歸併,即 兩個有序表組合成乙個新的有序表,如果還是不理解歸併排序,檢視我的另一篇部落格排序圖接
現在解決問題的思路有了,但面對的有這麼兩個問題:
1. 如何從鍊錶中獲取兩個有序鍊錶
2. 如何將兩個有序鍊錶整合成乙個新的有序鍊錶
對於問題1,解決方案:
每次查詢鍊錶的中間節點,將鍊錶從中間斷開,即 mid 的前乙個節點的next置為null,此時整個鍊錶分為前半段與後半段
前半段與後半段 分別繼續查詢中間節點,繼續分為 更小的前半段 與 更小後半段 (遞迴思想)
分到最後,會出現 前半段就是乙個節點,後半段也就是乙個節點 此時可以看作兩個都是有序的鍊錶,即此時從鍊錶中獲取到了兩個有序鍊錶
對於問題2,解決方案:
首先要是兩個頭節點有乙個為null,直接返回另乙個
兩個頭節點都不為空,val小的為新鍊錶的頭節點,定義工作指標p,遍歷root1 root2,p永遠指向小的,最後要是root1先為null,p.next就等於root2,反之p.next=root1
下面附上比較完整的**
public listnode sortlistii(listnode head)
listnode mid = slow.next;
slow.next = null;
listnode left = sortlistii(head);
listnode right = sortlistii(mid);
return concat(left,right);
}//二路歸併排序 快慢指標
public listnode concat(listnode root1,listnode root2)else
//工作節點
listnode p = root;
while (root1!=null && root2!=null)else
p = p.next;
}//連線上 最後剩下的有序鍊錶
p.next = root1==null ? root2 : root1;
//返回頭節點
return root;
}//二路合一
歸併排序(二路歸併)
歸併排序是一種遞迴思想的體現,通過多次合併較小的幾個 二路歸併為兩個 有序陣列形成新的有序表。思路 將陣列分為n nn個一元組,兩兩合併得到二元組,以此類推共合併log 2n log 2n log2 n 次後,陣列變得有序。時間複雜度為o n logn o nlogn o nlog n 編譯環境de...
二路歸併排序
不是困難的演算法,不過也是練習了下遞迴。include include include using namespace std const int maxn 100 5 int a maxn int b maxn void mergesort int a,int b,int begin,int en...
二路歸併排序
二路歸併排序是將兩個有序表合併成乙個有序表的排序方法。其基本思想為 序列中有 n個記錄,可以看作為 n個有序子串行,每個序列長度為 1。首先將每相鄰的兩個記錄合併,得到 n 2 個較大的有序子串行,每個序列長度為 2。再將上述子串行兩兩合併,得到 n 2 2 個有序子串行,直至得到乙個長度為 n的有...