problem:
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
.
题意:类似于快速排序的第一步,将乱序的链表分成两部分,小于target的放在前面,不小于target的放后面
thinking:
(1)利用快速排序的思想,将小于目标值的结点前移。但是,由于快速排序是不稳定的,所以不满足题目稳定性的要求,若套用快速排序必然是错的
(2)那就改造快速排序。快速排序的双指针游走方向是相反的,这就导致了排序的不稳定性。如果双指针同时沿着递增的方向游走,则是稳定的。
(3)对于本题,除了游走的双指针,还要增加前驱指针和最后一个小于目标值的后驱指针
code:
改造快速排序:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *partition(ListNode *head, int x) {
ListNode *p=NULL; //左指针
ListNode *after=NULL; //指向第一个不小于x的结点
ListNode *pre=head; //q的前驱结点
ListNode *q=head; //右指针
while(q!=NULL)
{
ListNode *tmp=q->next;
if(q->val<x)
{
if(after==NULL) //从第一个结点小于x
{
if(p==NULL)
{
p=q;
head=p;
}
else
p=p->next; //不用移动
}
else //第一个结点大于X
{
if(p==NULL)
{
p=q;
head=p;
p->next=after;
if(after->next==q) //p q之间只有一个结点不小于X
pre=after;
pre->next=tmp;
}
else
{
p->next=q;
p=p->next;
p->next=after;
if(after->next==q) //p q之间只有一个结点不小于X
pre=after;
pre->next=tmp;
}
}
}
else
{
if(after==NULL)
after=q;
pre=q; //连续结点不小于X
}
q=tmp;
}
return head;
}
};