题目指路:CM11 链表分割_牛客题霸_牛客网 (nowcoder.com)
现有一链表的头指针ListNode* pHead
,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针
错误思路:
遍历两遍链表
,第一次找小的数,第二次找大的数,但存在隐患,因为链表是连在一起的,将前面节点放到新的链表中,链表中的结构会紊乱
普通思路:
新定义一个哨兵的头节点,大于x的尾插,小于x的头插
结果:
可以看到方法是好方法,但是最后的结果顺序不对
我们任然需要切换思路
巧妙思路:
✏️链表和数组不同
,链表在链表的节点之间做手脚是不占用内存
,
✏️新建链表的节点去重新构建链表,只要把哨兵头节点free掉,就不存在占用空间
✏️既然要我们找比x小和比x大的数,分别放在两头,那么在第二种思路的基础上,我们不用同一个链表
,因为可以看到中间的哨兵头节点还需要一个指针去存储它的地址
✏️而且我们需要的都是尾插,因为尾插顺序不会改变
✏️两个链表,一个存储比x小,一个存储比x大,最后再将链表链接起来
准备好需要的哨兵节点,以及尾插需要的双指针
因为这里不需要走回头路,直接插入就行,上面的next指针可以省略
以 x = 3
为例
模拟第一步:
模拟第二步:
模拟第三步
注意这里greaterhead和lesstail的下一个都指向4
模拟第四步
模拟第五步
这里最后greatertail还连着lesstail,所以最后要把它们next都为NULL
最后变成:
代码如下:
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
if(pHead == NULL)
{
return NULL;
}
ListNode* cur = pHead;
ListNode* lesshead = (ListNode*)malloc(sizeof(ListNode));
ListNode* greaterhead = (ListNode*)malloc(sizeof(ListNode));
ListNode* lesstail = lesshead;
ListNode* greatertail = greaterhead;
while(cur)
{
if(cur->val < x)
{
lesstail->next = cur;
lesstail = cur;
cur = cur->next;
}
else
{
greatertail->next = cur;
greatertail = cur;
cur = cur->next;
}
}
greatertail->next = NULL;
lesstail->next = greaterhead->next;
ListNode* ret = lesshead->next;
free(greaterhead);
free(lesshead);
return ret;
}
};