我正在读《破解编码面试》一书,书中提出了一个链表分区问题:
给定一个链表和一个值x,将链表围绕一个值x进行分区,使小于x的所有节点位于大于或等于x的所有节点之前。
假设链表不是空的。
该解决方案来自Geeksforgeks网站,与《ctci:
// Function to make a new list
// (using the existing nodes) and
// return head of new list.
static Node partition(Node head, int x)
{
/* Let us initialize start and tail nodes of new list */
Node tail = head;
// Now iterate original list and connect nodes
Node curr = head;
while (curr != null)
{
Node next = curr.next;
if (curr.data < x)
{
/* Insert node at head. */
curr.next = head;
head = curr;
}
else // Append to the list of greater values
{
/* Insert node at tail. */
tail.next = curr;
tail = curr;
}
curr = next;
}
tail.next = null;
// The head has changed, so we need
// to return it to the user.
return head;
}
我不明白这个解决办法。这个算法是如何工作的?为什么是正确的?
1条答案
按热度按时间xsuvu9jc1#
试着这样想:
假设这是我们的链表
(0) -> (1) -> (2) -> (-1) -> (1) -> (-5)
(显然,链表看起来不像这样,但以我们的示例为例)以及
x = 0
是的next = curr.next
这样我们就不会“失去”下一个节点\我要从头到尾做记号
现在我们来看(0)它是否小于x(bcs它的头部和尾部)并不重要,所以它的指针指向它自己
现在我们来看(1)它也不小于x,所以(0)指向它,它就变成了^尾
[ *(0) -> ^(1)< ] [ (2) -> (-1) -> (1) -> (-5) ]
(这两份清单附在后面,但让我们想象一下它们的不同之处)同样的事情发生在(2)^尾巴上,它是-(1)指向它
现在我们看一下(-1),但是这次它比x小,所以它被设置为指向head,然后被设置为head
以此类推: