[路飞]_前端算法第四十九弹-分隔链表

121 阅读2分钟

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

示例 1:

输入:head = [1,4,3,2,5,2], x = 3 输出:[1,2,2,4,3,5]

示例 2:

输入:head = [2,1], x = 2 输出:[1,2]

如题所示,我们只需要找出比x小的部分和比x大的部分即可。也就是说我们只需要新建两个链表,small和large,比x小的全部放入small链表中,其余的全部放入large链表中,遍历完全部链表,将small链表的尾部连接到large的头部即可。

我们设立smallHead和largeHead两个哑结点,即他们的指针指向链表的头节点,这样做的目的是更方便地处理头节点为空的边界条件。同时设small和large节点指向当前链表的末尾节点。开始时smallHead = small,largeHead = large。随后,从前往后遍历链表,判断当前链表的节点值是否小于x,如果小于就将small.next指向该节点,否则将large的next指向该节点。

遍历结束后,我们将large.next置空,这样是因为当前节点复用的是原链表的节点,而其next指针可能指向一个小于x的节点, 我们需要切断这个引用。同时将small的next指针指向largeHead的next指针指向的节点,真正意义上的large列表的头节点。最后返回smallHead的next指针,即为所求。

var partition = function(head, x) {
    let small = new ListNode(0);
    const smallHead = small;
    let large = new ListNode(0);
    const largeHead = large;
    while (head !== null) {
        if (head.val < x) {
            small.next = head;
            small = small.next;
        } else {
            large.next = head;
            large = large.next;
        }
        head = head.next;
    }
    large.next = null;
    small.next = largeHead.next;
    return smallHead.next;
};
复制代码

复杂度分析

  • 时间复杂度:O(n),其中n是原链表的长度,我们对该链表进行了一次遍历。
  • 空间复杂度:O(1)。