給你鍊錶的頭結點 head ,請將其按 公升序 排列並返回 排序後的鍊錶 。高階:你可以在 o(n log n) 時間複雜度和常數級空間複雜度下,對鍊錶進行排序嗎?(題源自leetcode.148)
顯而易見的,對於鍊錶的排序,我們常常使用歸併排序,因此這裡我將給出三種解法:
首先強調一下,對於鍊錶的操作,最需要注意的幾點無非就是dummynode的使用,鍊錶的斷開和鍊錶的連線,掌握好這幾點,那麼很多鍊錶相關的問題就將迎刃而解了。1.自頂向下的歸併排序
類似於陣列的歸併排序,用的是遞迴,但是這裡與陣列的歸併不同的地方在於,我們是無法直接獲取鍊錶的中間位置的,因此我們必須通過使用快慢節點來找到中間節點,然後再依次對前半部分和後半部分進行歸併。
class solution
pre->next=null;
return merge(sortlist(head),sortlist(slow));
}listnode *merge(listnode *l1,listnode *l2)
else
}p->next=l1?l1:l2;
return l->next;
}};
2.自底向上的歸併排序
第1個和第三個方法很明顯並不能達到高階的要求,因為他們都使用了遞迴,空間複雜度至少為o(logn),因為遞迴的時候隱式地呼叫了棧,又因為該方法遞迴的模式是樹形的,高度為logn,空間複雜度也就是o(logn)。
那麼我們就選擇自底向上的歸併排序,這種歸併排序是不會使用到遞迴的,先2個2個地歸併,再4個4個…直到完全歸併完畢。
(使用到了cut和merge的**,可供參考)
class solution
for(int inv=1;invnext;
while(p)
}return dummy->next;
}listnode *cut(listnode *head,int x)
if(!newhead)return null;
listnode *tail=newhead;
newhead=newhead->next;
tail->next=null;
return newhead;
}listnode *merge(listnode *l1,listnode *l2)
else
}p->next=l1?l1:l2;
return head->next;
}};
3.快速排序
其實鍊錶的排序不僅可以歸併排序,也可以進行快速排序。至於為什麼快速排序一般不用於鍊錶的排序呢,其主要原因是快速排序的其中乙個優點就是它相對於歸併排序使用了更少的額外空間開銷,但是對於鍊錶的排序,本身就用不著額外的空間開銷,而且快速排序不穩定,因此歸併排序成了更好地選擇。
這裡給出快速排序的演算法,注意跟陣列排序有所區別,我們在劃分的時候,必須注意幾個點,主要就是dummynode和鍊錶斷開,連線的使用,這裡不再詳細描述。
class solution
listnode *quicksort(listnode* head,listnode* end)
listnode *partition(listnode *head, listnode *end)
else
}t->next=newhead;
head->next=temphead->next;
return newhead;
}};
鍊錶 排序鍊錶
樂扣原題 definition for singly linked list.public class listnode class solution 將鍊錶轉化為陣列 listlist new arraylist while null head 陣列遞增排序 collections.sort li...
鍊錶的排序
include stdio.h include malloc.h define len sizeof struct node typedef int datatype typedef struct node dlnode typedef dlnode dlist dlist create dlist...
鍊錶的排序
今天自己將職工管理系統用鍊錶的形式又重新寫了一遍,增刪改查的功都能實現,但是在對職工薪資進行排序的時候則遇到了問題,第一次碰到在煉表裡進行排序,想了很久也沒想出合適的方法,之後看了之前所用過的氣泡排序,發現完全可以用類似的方法來對薪資進行排序,下面則是鍊錶排序的具體 p temp7,max,n,m ...