原题如下:
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
.
ListNode *partition(ListNode *head, int x) {
if(head == NULL || head->next == NULL)
return head;
ListNode*smallRear,*bigHead,*preCur,*cur;
if(head->val < x){ //如果head结点比x小,则head即为当前smallRear,然后寻找bigHead
smallRear = head;
cur = head->next;
while(cur != NULL){
if(cur->val >= x){
break;
}
cur = cur->next;
smallRear = smallRear->next;
}
if(cur == NULL)//所有元素都比x小,直接返回
{
return head;
}
bigHead = cur;
preCur = cur;
cur = cur->next;
}
else //head结点不比x小,则head即为bigHead,需要往后寻找smallRear
{
bigHead = head;
preCur = head;
cur = head->next;
while(cur != NULL){
if(cur->val < x){
break;
}
preCur = cur;
cur = cur->next;
}
if(cur == NULL )//所有节点都不小于x,直接返回
{
return head;
}
preCur->next = cur->next;
cur->next = bigHead;
smallRear = cur;
head = cur;
cur = preCur->next;
}
while(cur != NULL){
if(cur->val < x){
preCur ->next = cur->next;
smallRear->next = cur;
cur->next = bigHead;
smallRear = cur;
cur = preCur->next;
}
else
{
preCur = cur;
cur = cur->next;
}
}
return head;
}
另外一种思路则比较简单,创建两个头结点,分别用来链接比x小的元素和比x大的元素,然后将两个链表进行连接即可,在编码时要注意将最后一个比x大的元素的next指针置空,否则有可能出现环。
ListNode *partition(ListNode *head, int x) {
if(head == NULL || head->next == NULL)
return head;
ListNode *p1 = new ListNode(0);
ListNode *p2 = new ListNode(0);
ListNode *pSmall = p1;
ListNode *pBig = p2;
while(head != NULL){
if(head->val < x){
pSmall->next = head;
pSmall = pSmall->next;
}
else
{
pBig->next = head;
pBig = pBig->next;
}
head = head->next;
}
pBig->next = NULL;
pSmall ->next = p2->next;
head = p1->next;
delete p1,p2;
return head;
}
两种方法对比发现,第一种思路没有申请额外的空间,但对链表的删除和插入操作较多,需要注意的细节问题较多(我也是经过三次提交才AC),而第二种方法则比较直观易懂,而且不容易出错,另外,链表头结点的存在确实方便了操作。