题目描述:
给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。你应当保留两个分区中每个节点的初始相对位置。
输入: head = 1->4->3->2->5->2, x = 3 输出: 1->2->2->4->3->5
思路:
先找到第一个大于等于x的节点curr,然后继续往后,如果碰到小于x的节点pNode,就把该节点插入curr前面。
注意:
1. 要区分curr是否为头结点的情况,如果是头结点,则插入pNode的操作不一样,而且插入之后要把pNode设置为头结点。
2. 如果curr是头结点,插入一个节点在前面之后就不是头结点了,所以不能只在最开始按curr是不是头结点来确定操作,应该在要每次插入元素之前判断。
3. 如果碰到的节点pNode是大于等于x的,只需要将pNodePre和pNode往后走一步即可。
4. 如果碰到了一个小于x的节点pNode,
正常的,如果curr不是头结点。先将这个节点从当前位置删掉,再插入curr前。将这个节点从当前位置删掉时需要知道pNode前一个指针,所以维护pNodePre的值,令pNodePre->next=pNode->next;即可。将删除的pNode插入curr前也需要知道curr前一个指针,所以需要维护pre的值,令pre->next=pNode; pNode->next=curr;即可。然后pre指向pNode(此时curr前一个变为pNode),pNode指向pNodePre的下一个。
如果curr是头结点。还是先将这个节点从当前位置删掉,与上面同样的操作。下一步将pNode插入curr前。此时pre的值为空,令pNode->next=curr;head=pNode; 然后pre需要指向pNode,pNode还是指向pNodePre的下一个。
AC代码
/**
* 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) {
if(head==NULL||head->next==NULL)
return head;
ListNode* pre=NULL;
ListNode* curr=head;
while(curr->next&&curr->val<x)
{
pre=curr;
curr=curr->next;
}
ListNode* pNode=curr->next;
ListNode* pNodePre=curr;
while(pNode)
{
if(pNode->val<x)
{
if(curr==head)
{
pNodePre->next=pNode->next;
pNode->next=curr;
head=pNode;
pre=pNode;
pNode=pNodePre->next;
}
else
{
pNodePre->next=pNode->next;
pre->next=pNode;
pNode->next=curr;
pre=pNode;
pNode=pNodePre->next;
}
}
else
{
pNodePre=pNodePre->next;
pNode=pNode->next;
}
}
return head;
}
};
通过上面的分析可以发现两种情况下有一些操作是一样的,程序还可以优化如下
/**
* 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) {
if(head==NULL||head->next==NULL)
return head;
ListNode* pre=NULL;
ListNode* curr=head;
while(curr->next&&curr->val<x)
{
pre=curr;
curr=curr->next;
}
ListNode* pNode=curr->next;
ListNode* pNodePre=curr;
while(pNode)
{
if(pNode->val<x)
{
pNodePre->next=pNode->next;
if(curr==head)
{
pNode->next=curr;
head=pNode;
}
else
{
pre->next=pNode;
pNode->next=curr;
}
pre=pNode;
pNode=pNodePre->next;
}
else
{
pNodePre=pNodePre->next;
pNode=pNode->next;
}
}
return head;
}
};