双虚头法分隔单链表

题目

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有小于 x 的节点都出现在大于或等于 x 的节点之前。你应当保留两个分区中每个节点的初始相对位置。示例如下:
在这里插入图片描述
输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]

解决思路

  • 创建两个虚拟头节点small和big,创建两个指针s和b分别指向虚拟头结点small和big,创建指针q记录head的下一个节点。
  • 遍历链表,当节点的值小于给定的值时,将该节点链入到samll对应的链表中(注意对应指针要向前移动)。
  • 当节点的值大于给定的值时,将该节点链入big对应的链表中(注意对应指针要向前移动)。
  • 最后将small对应的链表和big对应的链表合并为一条链表。

代码

  • C++代码
# include <stdio.h>

struct ListNode {
    int val;
    ListNode *next;
    ListNode(): val(0), next(nullptr) {}
    ListNode(int val): val(val), next(nullptr) {}
    ListNode(ListNode *next): val(0), next(next) {}
    ListNode(int val, ListNode *next): val(val), next(next) {}
};


class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        if (nullptr == head) {
            return head;
        }

        ListNode small;     // 虚拟头节点1
        ListNode big;       // 虚拟头节点2
        ListNode *s = &small;   // 链表分隔后,s指向small所在链表的尾结点
        ListNode *b = &big;     // 链表分隔后,b指向big所在链表的尾结点
        ListNode *h = head;
        ListNode *q;            // 记录h的下一个节点

        // 遍历每一个节点,判断将节点的值与给定的值的大小
        while (h) {
            q = h->next;
            if (h->val < x) {       // 节点的值小于给定的值,将该节点链入small对应的链表中
                h->next = s->next;  // 即h->next = nullptr
                s->next = h;
                s = h;
            } else {                // 节点的值大于给定的值,将该节点链入big对应的链表中
                h->next = b->next;	// 即h->next = nullptr
                b->next = h;        
                b = h;
            }
            h = q;
        }
        s->next = big.next;         // 将small和big对应的链表连接成一条链表
        return small.next;
    }

};


int main() {
    ListNode *a = new ListNode(1);
    ListNode *b = new ListNode(4);
    ListNode *c = new ListNode(3);
    ListNode *d = new ListNode(2);
    ListNode *e = new ListNode(5);
    ListNode *f = new ListNode(2);
    ListNode *head = a;

    a->next = b;
    b->next = c;
    c->next = d;
    d->next = e;
    e->next = f;

    printf("before split: ");
    while (head) {
        printf("%d ", head->val);
        head = head->next;
    }
    printf("\n");
    head = a;

    int k = 3;
    Solution *solution = new Solution();
    ListNode *ret = solution->partition(head, k);
    
    printf("after split: ");
    while (ret) {
        printf("%d ", ret->val);
        ret = ret->next;
    }
    
    return 0;
}
  • python代码
# -*- coding: utf-8 -*-

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        if not head:
            return head

        small: ListNode = ListNode()        # 虚拟头节点1
        big: ListNode = ListNode()          # 虚拟头节点2
        s: ListNode = small                 # 链表分隔后,s指向small所在链表的尾结点
        b: ListNode = big                   # 链表分隔后,b指向big所在链表的尾结点
        h: ListNode = head
        q: ListNode                         # 记录h的下一个节点

        # 遍历每一个节点,判断将节点的值与给定的值的大小
        while h:
            q = h.next
            if h.val < x:           # 节点的值小于给定的值,将该节点链入small对应的链表中
                h.next = s.next     # 即h->next = None
                s.next = h
                s = h
            else:                   # 节点的值大于给定的值,将该节点链入big对应的链表中
                h.next = b.next     # 即h->next = None;
                b.next = h
                b = h

            h = q

        s.next = big.next           # 将small和big对应的链表连接成一条链表
        return small.next

def main():
    a: ListNode = ListNode(1)
    b: ListNode = ListNode(4)
    c: ListNode = ListNode(3)
    d: ListNode = ListNode(2)
    e: ListNode = ListNode(5)
    f: ListNode = ListNode(2)
    head: ListNode = a

    a.next = b
    b.next = c
    c.next = d
    d.next = e
    e.next = f

    print("before split: ", end='')
    while head:
        print(head.val, end=' ')
        head = head.next
    print()

    head = a
    k: int = 3
    solution: Solution = Solution()
    ret: ListNode = solution.partition(head, k)

    print("after split: ", end='')
    while ret:
        print(ret.val, end=' ')
        ret = ret.next


if __name__ == "__main__":
    main()

说明

  • 对应LeetCode第86题。
  • 链接:https://leetcode-cn.com/problems/partition-list/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值