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

我现在正在阅读Cracking the Coding Interview这本书,它提出了一个链表分区问题:

给定一个链表和一个值 x,围绕一个值 x 划分一个链表,使得所有小于 x 的节点排在所有大于或等于 x 的节点之前。

假设链表不为空。

The solution 取自 GeeksForGeeks 网站,与 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;  
}

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

hardss 回答:这个链表分区算法是如何工作的?

试着这样想:

假设这是我们的链表 (0) -> (1) -> (2) -> (-1) -> (1) -> (-5)(显然链表不是这样,但对于我们的示例)

还有x = 0

我们做 next = curr.next 是为了不“丢失”下一个节点

\ 我要标记 *head 和 ^tail

现在我们看 (0) 它是否小于 x 并不重要(bcs 它的头和尾)所以它的指针转向自身

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

现在我们看 (1) 它也不小于 x 所以 (0) 指向它,它变成 ^tail

[ *(0) -> ^(1)< ] [ (2) -> (-1) -> (1) -> (-5) ](附有两个列表,但让我们想象一下它们没有)

同样的事情发生在 (2) ^tail 是 - (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)<  ] [ ]
本文链接:https://www.f2er.com/1154614.html

大家都在问