Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2
and x = 3,
return 1->2->2->4->3->5
.
这道题是将一个链表分为前后两部分,前一部分小于目标元素,后一部分大于或等于目标元素,并且保持元素原来的相对位置不变。
和快拍的一步partition比较相似,但是思路完全不同。因为快排是交换元素,这里要求保持元素的相对顺序不变。
要完成这个任务肯定要遍历一遍链表,因此时间复杂度可以做到O(n),那就尽可能做到原址操作,空间复杂度做到O(1)。
用四个指针分别指向较大元素和较小元素的部分的头和尾,就可以实现这一目标。很简单。
class Solution {
public:
ListNode *partition(ListNode *head, int x) {
ListNode *p = head;
ListNode *greater = NULL, *less = NULL, *g = NULL, *l = NULL;
while (NULL != p){
if (p->val >= x){
if (NULL == greater){
greater = p;
g = p;
}
else
{
g->next = p;
g = p;
}
}
else{
if (NULL == less){
less = p;
l = p;
}
else
{
l->next = p;
l = p;
}
}
p = p->next;
}
if (NULL == less)
return greater;
l->next = greater;
if (g)
g->next = NULL;
return less;
}
};
写完之后发现代码好不简洁,又臭又长,那就只好用dummy了,代码可以简化很多,还可以以减少很所判断。
class Solution {
public:
ListNode *partition(ListNode *head, int x) {
ListNode *p = head;
ListNode *greater = new ListNode(0);
ListNode *less = new ListNode(0);
ListNode *g = greater, *l = less;
while (NULL != p){
if (p->val >= x){
g->next = p;
g = p;
}
else{
l->next = p;
l = p;
}
p = p->next;
}
if (g)
g->next = NULL;
l->next = greater->next;
return less->next;
}
};