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) {
ListNode *dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode *part1Tail = dummyHead, *part2Tail = dummyHead;
while (part1Tail->next && part1Tail->next->val < x) {
part1Tail = part1Tail->next;
part2Tail = part2Tail->next;
}
while (part1Tail->next && part2Tail->next) {
if (part2Tail->next->val >= x)
part2Tail = part2Tail->next;
else {
ListNode *moveNode = part2Tail->next;
part2Tail->next = part2Tail->next->next;
moveNode->next = part1Tail->next;
part1Tail->next = moveNode;
part1Tail = moveNode;
}
}
return dummyHead->next;
}
Run Time: 68ms
更清晰的解法
思路:生成两条链表,小于x的插入到part1的尾部,其余的插入到part2的尾部;最后将两条链表连接起来即可。
ListNode *partition(ListNode *head, int x) {
ListNode *part1DummyHead = new ListNode(0), *part2DummyHead = new ListNode(0);
ListNode *part1Tail = part1DummyHead, *part2Tail = part2DummyHead;
for (ListNode *cur = head; cur != NULL; cur = cur->next) {
if (cur->val < x) {
part1Tail->next = cur;
part1Tail = cur; // No need to set cur->next as NULL
}
else {
part2Tail->next = cur;
part2Tail = cur; // No need to set cur->next as NULL
}
}
part1Tail->next = part2DummyHead->next;
part2Tail->next = NULL;
return part1DummyHead->next;
}
Run Time: 72ms
更精简的代码
可用指向指针的指针消除两行重复代码。
ListNode *partition(ListNode *head, int x) {
ListNode *part1DummyHead = new ListNode(0), *part2DummyHead = new ListNode(0);
ListNode *part1Tail = part1DummyHead, *part2Tail = part2DummyHead;
for (ListNode *cur = head; cur != NULL; cur = cur->next) {
ListNode **optTail = cur->val < x ? &part1Tail : &part2Tail;
(*optTail)->next = cur;
(*optTail) = cur; // No need to set cur->next as NULL
}
part1Tail->next = part2DummyHead->next;
part2Tail->next = NULL;
return part1DummyHead->next;
}
Run Time: 44ms
更好地,可用指针数组消除循环内的判断。
ListNode *partition(ListNode *head, int x) {
ListNode *part1DummyHead = new ListNode(0), *part2DummyHead = new ListNode(0);
ListNode *partTails[2] = {part1DummyHead, part2DummyHead};
for (ListNode *cur = head; cur != NULL; cur = cur->next) {
partTails[cur->val >= x]->next = cur;
partTails[cur->val >= x] = cur; // No need to set cur->next as NULL
}
partTails[0]->next = part2DummyHead->next;
partTails[1]->next = NULL;
return part1DummyHead->next;
}
Run Time: 20ms
可参见:C语言优化实例:循环中减少判断
注:以上各解法,时间复杂度均为O(N),空间复杂度均为O(1)。以上各解法均未考虑内存泄露的问题。