sort a linked list in o(n log n) time using constant space complexity.
對乙個鍊錶進行排序,且時間複雜度要求為 o(n log n) ,空間複雜度為常量。一看到 o(n log n) 的排序,首先應該想到歸併排序和快速排序,但是通常我們使用這兩種排序方法時都是針對陣列的,現在是鍊錶了。
歸併排序法:在動手之前一直覺得空間複雜度為常量不太可能,因為原來使用歸併時,都是 o(n)的,需要複製出相等的空間來進行賦值歸併。對於鍊錶,實際上是可以實現常數空間占用的。利用歸併的思想,遞迴地將當前鍊錶分為兩段,然後merge,分兩段的方法是使用 fast-slow 法,用兩個指標,乙個每次走兩步,乙個走一步,知道快的走到了末尾,然後慢的所在位置就是中間位置,這樣就分成了兩段。merge時,把兩段頭部節點值比較,用乙個 p 指向較小的,且記錄第乙個節點,然後 兩段的頭一步一步向後走,p也一直向後走,總是指向較小節點,直至其中乙個頭為null,處理剩下的元素。最後返回記錄的頭即可。**如下:
[cpp]
view plain
copy
?de上檢視**片" href="https://co%3cwbr%3ede.csdn.net/snippets/239101" style="color:rgb(160,160,160); line-height:21px; text-decoration:none; border:none; padding:0px; margin:0px 10px 0px 0px; font-size:9px; background-color:inherit" rel="noopener noreferrer">
classsolution
listnode * mergesort(listnode *head)
pre->next=null;
listnode *lhalf=mergesort(head);
listnode *rhalf=mergesort(p); //recursive
returnmerge(lhalf, rhalf);
//merge
} listnode * merge(listnode *lh, listnode *rh)
else
p=p->next;
}if(!lh)
p->next=rh;
else
p->next=lh;
p=temp->next;
temp->next=null;
deletetemp;
returnp;
} };
快速排序:使用快排也行,就是每次利用頭節點作為基準,將小於它的交換到鍊錶左側,大於它的放在右側,最後把它換到中間某個位置,然後遞迴處理左側和右側。但是相對於歸併來說,它的元素交換次數太多了,可能會超時。
對鍊錶進行排序
對鍊錶進行排序 參考的思路是來自於這位 哥們 definition for singly linked list.struct listnode class solution listnode rt sort head return rt listnode sort listnode begin 鍊...
鍊錶排序 147 對鍊錶進行插入排序
對鍊錶進行插入排序。插入排序的動畫演示如上。從第乙個元素開始,該鍊錶可以被認為已經部分排序 用黑色表示 每次迭代時,從輸入資料中移除乙個元素 用紅色表示 並原地將其插入到已排好序的鍊錶中。插入排序演算法 插入排序是迭代的,每次只移動乙個元素,直到所有元素可以形成乙個有序的輸出列表。每次迭代中,插入排...
對鍊錶進行排序(歸併排序)
首先用快慢指標的方法找到鍊錶中間節點,然後遞迴的對兩個子鍊錶排序,把兩個排好序的子鍊錶合併成一條有序的鍊錶。歸併排序應該算是鍊錶排序最佳的選擇了 保證了最好和最壞時間複雜度都是nlogn,而且它在陣列排序中廣受詬病的空間複雜度在鍊錶排序中也從o n 降到了o 1 class solution fas...