8道链表常考题-链表划分

在这里插入图片描述
8道链表常考题-链表划分_第1张图片

LeetCode官方题解
本题要求我们改变链表结构,使得值小于 x的元素,位于值大于等于x元素的前面。这实质上意味着在改变后的链表中有某个点,在该点之前的元素全部小于x ,该点之后的元素全部 大于等于x。 我们将这个点记为JOINT。
8道链表常考题-链表划分_第2张图片
对该问题的逆向工程告诉我们,如果我们在JOINT将改后链表拆分,我们会得到两个更小的链表,其中一个包括全部值小于x的元素,另一个包括全部值大于x的元素。在解法中,我们的主要目的是创建这两个链表,并将它们连接。
双指针法:我们可以用两个指针before 和 after 来追踪上述的两个链表。两个指针可以用于分别创建两个链表,然后将这两个链表连接即可获得所需的链表。
初始化两个指针 before 和 after。在实现中,我们将两个指针初始化为哑 ListNode。这有助于减少条件判断。(不信的话,你可以试着写一个不带哑结点的方法自己看看!)
8道链表常考题-链表划分_第3张图片
利用head指针遍历原链表。
若head 指针指向的元素值 小于 x,该节点应当是 before 链表的一部分。因此我们将其移到 before 中。
8道链表常考题-链表划分_第4张图片
否则,该节点应当是after 链表的一部分。因此我们将其移到 after 中。
8道链表常考题-链表划分_第5张图片
遍历完原有链表的全部元素之后,我们得到了两个链表 before 和 after。原有链表的元素或者在before 中或者在 after 中,这取决于它们的值。
8道链表常考题-链表划分_第6张图片
注意: 由于我们从左到右遍历了原有链表,故两个链表中元素的相对顺序不会发生变化。另外值得注意的是,在图中我们完好地保留了原有链表。事实上,在算法实现中,我们将节点从原有链表中移除,并将它们添加到别的链表中。我们没有使用任何额外的空间,只是将原有的链表元素进行移动。
现在,可以将 before 和 after 连接,组成所求的链表。
8道链表常考题-链表划分_第7张图片

为了算法实现更容易,我们使用了哑结点初始化。不能让哑结点成为返回链表中的一部分,因此在组合两个链表时需要向前移动一个节点。

Java

class Solution {
    public ListNode partition(ListNode head, int x) {

        // before and after are the two pointers used to create the two list
        // before_head and after_head are used to save the heads of the two lists.
        // All of these are initialized with the dummy nodes created.
        ListNode before_head = new ListNode(0);
        ListNode before = before_head;
        ListNode after_head = new ListNode(0);
        ListNode after = after_head;

        while (head != null) {

            // If the original list node is lesser than the given x,
            // assign it to the before list.
            if (head.val < x) {
                before.next = head;
                before = before.next;
            } else {
                // If the original list node is greater or equal to the given x,
                // assign it to the after list.
                after.next = head;
                after = after.next;
            }

            // move ahead in the original list
            head = head.next;
        }

        // Last node of "after" list would also be ending node of the reformed list
        after.next = null;
         // Once all the nodes are correctly assigned to the two lists,
        // combine them to form a single list which would be returned.
        before.next = after_head.next;

        return before_head.next;
    }
}

C++实现
8道链表常考题-链表划分_第8张图片
8道链表常考题-链表划分_第9张图片
8道链表常考题-链表划分_第10张图片

我的实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode *ltpart = NULL;
        ListNode *ltpartend = NULL;
        ListNode *btpart = NULL;
        ListNode *btpartend = NULL;
        if(head == NULL) return NULL;
        while(head)
        {
            if(head->val < x){
                //insert(ltpart,head);
                if(ltpart == NULL){
                    ltpart = head;
                }else{
                    ltpartend->next = head; 
                }
                ltpartend = head; //记录尾节点
            }else{
                //insert(btpart,head);
                if(btpart == NULL){
                    btpart = head;
                }else{
                    btpartend->next = head;
                }
                btpartend = head;
            }
            
            head = head->next;
        }
        if(ltpartend == NULL){
            btpartend->next = NULL;
            return btpart;
        }else{
            ltpartend->next = btpart;
            if(btpart != NULL)
            {
                btpartend->next = NULL;
            }
            return ltpart;
        }
    }
    
};

你可能感兴趣的:(算法,leetcode)