leetcode
leetcode 2651 ~ 2700
分割链表

分割链表

难度:

标签:

题目描述

Write code to partition a linked list around a value x, such that all nodes less than x come before all nodes greater than or equal to x. If x is contained within the list, the values of x only need to be after the elements less than x (see below). The partition element x can appear anywhere in the "right partition"; it does not need to appear between the left and right partitions.

Example:

Input: head = 3->5->8->5->10->2->1, x = 5
Output: 3->1->2->10->5->5->8

代码结果

运行时间: 32 ms, 内存: 14.9 MB


/*
 * Problem: Partition a linked list such that all nodes less than x come before nodes greater than or equal to x.
 * Approach (Java Streams simulation):
 * 1. Since Java Streams are not directly applicable to linked lists in this way, 
 *    simulate the functionality by creating helper methods.
 * 2. This example simulates stream processing without using Java Streams.
 */

import java.util.ArrayList;
import java.util.List;

public class Solution {
    public ListNode partition(ListNode head, int x) {
        List<ListNode> nodes = new ArrayList<>();
        ListNode current = head;
        // Collect nodes into a list
        while (current != null) {
            nodes.add(current);
            current = current.next;
        }
        // Partition nodes by the value x
        List<ListNode> lessThanX = new ArrayList<>();
        List<ListNode> greaterOrEqualX = new ArrayList<>();
        for (ListNode node : nodes) {
            if (node.val < x) {
                lessThanX.add(node);
            } else {
                greaterOrEqualX.add(node);
            }
        }
        // Combine lists
        ListNode dummy = new ListNode(0);
        current = dummy;
        for (ListNode node : lessThanX) {
            current.next = node;
            current = current.next;
        }
        for (ListNode node : greaterOrEqualX) {
            current.next = node;
            current = current.next;
        }
        current.next = null; // End the list
        return dummy.next;
    }
}

解释

方法:

题解采用了双链表的方式来解决问题。首先创建两个哑节点left和right,分别用来构建小于x和大于等于x的两部分链表。遍历原链表,根据每个节点的值,将其分别链接到left或right链表的尾部。最终,将两个链表连接起来,形成最终的分割链表。这种方法不保留节点在各分区的相对位置,但确保所有小于x的节点都位于大于或等于x的节点前面。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
在实现分割链表时,为什么选择使用双链表结构而不是在原链表上直接进行调整?
使用双链表结构可以简化节点的重新链接过程,并减少复杂的指针操作。在原链表上直接进行节点的调整需要多次遍历以确定节点的正确位置,并可能涉及到复杂的节点前驱和后继的处理,这不仅增加了实现的难度,也有可能引入错误。通过创建两个哑节点作为新链表的头部,可以方便地将节点分类并连接,避免了修改原链表的结构,使得操作更为直观和安全。
🦆
你是如何保证在连接两个链表时不会出现循环引用或其他链表错误?
在连接两个链表之前,通过设置每个节点的next指针为None,确保了每个节点被独立处理并从原链表中断开,这样可以防止未预期的循环引用。连接两个链表时,只涉及将第一个链表的最后一个节点的next指针指向第二个链表的第一个有效节点(right链表的哑节点的next节点),这样的操作简单且不容易出错。通过明确的结束和连接步骤,可以确保链表的正确性和完整性。
🦆
对于边界情况,如链表完全为空或链表中所有元素都小于(或等于)x,这段代码是否有特殊处理,能否保证正确输出?
代码中已经考虑了链表为空的情况。在while循环开始之前,如果head为None,则循环不会执行,最终函数返回p.next,即为None,符合空链表的预期输出。对于链表中所有元素都小于或等于x的情况,这些元素将全部链接到left或right链表中,而另一个链表将保持为空。连接操作中,如果一个链表为空,则其对应的哑节点的next也将为None,不会影响最终链表的正确性。这样确保了在所有边界情况下,代码都能给出正确的输出。

相关问题