快速排序1(算法只交换节点的val值,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))
这里的partition我们参考数组快排partition的第二种写法(选取第一个元素作为枢纽元的版本,因为链表选择最后一元素需要遍历一遍),具体可以参考here
这里我们还需要注意的一点是数组的partition两个参数分别代表数组的起始位置,两边都是闭区间,这样在排序的主函数中:
void
quicksort(vector<
int
>&arr,
int
low,
int
high)
{
if
(low < high)
{
int
middle = mypartition(arr, low, high);
quicksort(arr, low, middle-1);
quicksort(arr, middle+1, high);
}
}
class Solution {
public:
ListNode *quickSortList(ListNode *head) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
//链表快速排序
if(head == NULL || head->next == NULL)return head;
qsortList(head, NULL);
return head;
}
void qsortList(ListNode*head, ListNode*tail)
{
//链表范围是[low, high)
if(head != tail && head->next != tail)
{
ListNode* mid = partitionList(head, tail);
qsortList(head, mid);
qsortList(mid->next, tail);
}
}
ListNode* partitionList(ListNode*low, ListNode*high)
{
//链表范围是[low, high)
int key = low->val;
ListNode* loc = low;
for(ListNode*i = low->next; i != high; i = i->next)
if(i->val < key)
{
loc = loc->next;
swap(i->val, loc->val);
}
swap(loc->val, low->val);
return loc;
}
};
快速排序2(算法交换链表节点,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))
这里的partition,我们选取第一个节点作为枢纽元,然后把小于枢纽的节点放到一个链中,把不小于枢纽的及节点放到另一个链中,最后把两条链以及枢纽连接成一条链。
这里我们需要注意的是,1.在对一条子链进行partition时,由于节点的顺序都打乱了,所以得保正重新组合成一条新链表时,要和该子链表的前后部分连接起来,因此我们的partition传入三个参数,除了子链表的范围(也是前闭后开区间),还要传入子链表头结点的前驱;2.partition后链表的头结点可能已经改变
class Solution {
public:
ListNode *quickSortList(ListNode *head) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
//链表快速排序
if(head == NULL || head->next == NULL)return head;
ListNode tmpHead(0); tmpHead.next = head;
qsortList(&tmpHead, head, NULL);
return tmpHead.next;
}
void qsortList(ListNode *headPre, ListNode*head, ListNode*tail)
{
//链表范围是[low, high)
if(head != tail && head->next != tail)
{
ListNode* mid = partitionList(headPre, head, tail);//注意这里head可能不再指向链表头了
qsortList(headPre, headPre->next, mid);
qsortList(mid, mid->next, tail);
}
}
ListNode* partitionList(ListNode* lowPre, ListNode* low, ListNode* high)
{
//链表范围是[low, high)
int key = low->val;
ListNode node1(0), node2(0);//比key小的链的头结点,比key大的链的头结点
ListNode* little = &node1, *big = &node2;
for(ListNode*i = low->next; i != high; i = i->next)
if(i->val < key)
{
little->next = i;
little = i;
}
else
{
big->next = i;
big = i;
}
big->next = high;//保证子链表[low,high)和后面的部分连接
little->next = low;
low->next = node2.next;
lowPre->next = node1.next;//为了保证子链表[low,high)和前面的部分连接
return low;
}
};