这个链表分区算法是如何工作的?

9w11ddsr  于 2021-06-27  发布在  Java
关注(0)|答案(1)|浏览(353)

我正在读《破解编码面试》一书,书中提出了一个链表分区问题:
给定一个链表和一个值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;  
}

我不明白这个解决办法。这个算法是如何工作的?为什么是正确的?

xsuvu9jc

xsuvu9jc1#

试着这样想:
假设这是我们的链表 (0) -> (1) -> (2) -> (-1) -> (1) -> (-5) (显然,链表看起来不像这样,但以我们的示例为例)
以及 x = 0 是的 next = curr.next 这样我们就不会“失去”下一个节点
\我要从头到尾做记号
现在我们来看(0)它是否小于x(bcs它的头部和尾部)并不重要,所以它的指针指向它自己

[*^(0)<  ] [  (1) -> (2) -> (-1) -> (1) -> (-5) ]

现在我们来看(1)它也不小于x,所以(0)指向它,它就变成了^尾 [ *(0) -> ^(1)< ] [ (2) -> (-1) -> (1) -> (-5) ] (这两份清单附在后面,但让我们想象一下它们的不同之处)
同样的事情发生在(2)^尾巴上,它是-(1)指向它

[ *(0) -> (1) -> ^(2)<  ] [  (-1) -> (1) -> (-5) ]

现在我们看一下(-1),但是这次它比x小,所以它被设置为指向head,然后被设置为head

[ *(-1) -> (0) -> (1) -> ^(2)<  ] [  (1) -> (-5) ]

以此类推:

[ *(-1) -> (0) -> (1) -> (2) -> ^(1)<  ] [ (-5) ]

[ *(-5) -> (-1) -> (0) -> (1) -> (2) -> ^(1)<  ] [ ]

相关问题