当然可以!下面是一个详细的技术博客,涵盖了题目解读、解题思路、代码实现以及注意事项。
题目解读
给定一个单链表和一个整数 x
,要求重新排列链表,使得所有小于 x
的节点都排在前面,所有大于或等于 x
的节点都排在后面。同时,保持原有的相对顺序不变。
示例
输入:1->7->8->3->4->5->5->6->1
,x = 5
输出:1->3->4->1->7->8->5->5->6
解题思路
-
分割链表:
- 创建两个虚拟头节点
lGuard
和gGuard
,分别用于存储小于x
的节点和大于或等于x
的节点。 - 使用两个指针
lTail
和gTail
来记录当前链表的尾部位置,以便进行尾插操作。
- 创建两个虚拟头节点
-
遍历链表:
- 使用指针
cur
遍历原始链表。 - 根据节点值的大小,将节点插入到相应的链表中。
- 使用指针
-
合并链表:
- 将
gGuard
链表连接到lGuard
链表的末尾。 - 返回新的链表头节点。
- 将
代码实现
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
struct ListNode*cur=pHead;
struct ListNode* gGuard, *gTail, *lGuard, *lTail;
gGuard = gTail = (struct ListNode*)malloc(sizeof(struct ListNode));
if (gGuard) {
perror("malloc fail");
}
lGuard = lTail = (struct ListNode*)malloc(sizeof(struct ListNode));
if (lGuard) {
perror("malloc fail");
}
while (pHead) {
if (pHead->val < x) {
lTail->next = pHead;
lTail = lTail->next;
} else {
gTail->next = pHead;
gTail = gTail->next;
}
pHead = pHead->next;
}
gTail->next = NULL;
lTail->next = gGuard->next;
pHead = lGuard->next;
free(gGuard);
free(lGuard);
return pHead;
}
};
注意事项
-
虚拟头节点:
- 使用虚拟头节点可以避免处理空指针的问题,简化代码逻辑。
- 虚拟头节点在最后会被释放,不会影响最终结果。(记住释放)
-
尾指针:
- 使用尾指针
lTail
和gTail
记录当前链表的尾部位置,可以高效地进行尾插操作,避免每次查找尾部节点。
- 使用尾指针
-
内存管理:
- 在函数结束时,释放虚拟头节点的内存,避免内存泄漏。
总结
通过使用虚拟头节点和尾指针,我们可以高效地将链表分割成两部分,并按要求重新组合。这种方法不仅简洁,而且易于理解。希望这篇博客对你有所帮助!如果有任何问题或需要进一步的解释,请随时提问。
OJ链接