LeetCode 725 分隔链表

本文介绍了一种将链表分隔为k个连续部分的算法,确保每部分长度尽可能相等,差距不超过1。通过计算链表长度和k的商与余数,实现链表的均匀分段,适用于多种场景。

题目

给定一个头结点为 root 的链表, 编写一个函数以将链表分隔为 k 个连续的部分。
每部分的长度应该尽可能的相等: 任意两部分的长度差距不能超过 1,也就是说可能有些部分为 null。
这k个部分应该按照在链表中出现的顺序进行输出,并且排在前面的部分的长度应该大于或等于后面的长度。
返回一个符合上述规则的链表的列表。

== 举例: 1->2->3->4, k = 5 // 5 结果 [ [1], [2], [3], [4], null ]==
示例 1:

-输入:
root = [1, 2, 3], k = 5
输出: [[1],[2],[3],[],[]]
解释:
输入输出各部分都应该是链表,而不是数组。
例如, 输入的结点 root 的 val= 1, root.next.val = 2, \root.next.next.val = 3, 且 root.next.next.next = null。
第一个输出 output[0] 是 output[0].val = 1, output[0].next = null。
最后一个元素 output[4] 为 null, 它代表了最后一个部分为空链表。
示例 2:

输入:
root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3
输出: [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
解释:
输入被分成了几个连续的部分,并且每部分的长度相差不超过1.前面部分的长度大于等于后面部分的长度。

思路

我们先对给定的链表求长度,然后除以k,会得到一个商和余数,商的数值代表平均分为k段之后每段有多少个节点,余数的数值代表前多少段需要多加一个节点,商和余数总共有以下几个情况:

  • (1)0商为0,余数为0。
    此时说明链表长度就是0,也不需要做什么处理,直接返回一个空数组就行。

  • (2)商为0,余数不为0。
    说明此时的链表长度是小于k的,就如例1一样,商为0,余数为3。说明平均分为5段之后,平均每段有0个节点,然后前3段需要多加一个节点,那么正好就是:[1]、[2]、[3]、[]、[]。

  • (3)商不为0,余数为0。
    说明此时正好能够将链表平均分为k段,每段的长度就是商的数值了。

  • (4)商不为0,余数不为0。
    此时说明能将链表分为k段,但是还有多余的节点。而题中规定了各个分段的长度相差不能大于1,那么我们就只能让这多出的节点再次分给每段,而且每段只能分一个。并且题中还规定了前面的长度要比后面的常,所以我们就应该按照段的顺序再给分配一个了。需要注意这里的节点顺序不能乱。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def splitListToParts(self, root, k):
        """
        :type root: ListNode
        :type k: int
        :rtype: List[ListNode]
        """
        count = 0
        p= root
        node =[]
        while p:
            count +=1
            p =p.next
        num = count/k
        re= count %k
        for i in range(k):
            head = ListNode(0)
            p = head
            for j in range(num):
                nodes = ListNode(root.val)
                p.next = nodes
                p = p.next
                root = root.next
            if re and root:
                rnode = ListNode(root.val)
                p.next = rnode
                if root:
                    root = root.next
                re -=1
            node.append(head.next)
        return node
                
        
        
### LeetCode 86 分隔链表 C语言实现 以下是基于题目描述和需求编写的 C 语言解决方案: ```c typedef struct ListNode { int val; struct ListNode* next; } ListNode; struct ListNode* partition(struct ListNode* head, int x) { if (head == NULL || head->next == NULL) return head; // 如果链表为空或者只有一个节点,直接返回原链表 // 创建两个虚拟头结点分别存储小于x的部分和大于等于x的部分 struct ListNode smallDummy = {0}, largeDummy = {0}; struct ListNode *small = &smallDummy, *large = &largeDummy; struct ListNode* current = head; while (current != NULL) { if (current->val < x) { small->next = current; // 将当前节点加入到小于x的部分 small = small->next; } else { large->next = current; // 将当前节点加入到大于等于x的部分 large = large->next; } current = current->next; // 移动到下一个节点 } // 处理边界情况:最后一个节点的next应置为NULL以防成环 large->next = NULL; small->next = largeDummy.next; // 连接两部分链表 return smallDummy.next; // 返回新的头部 } ``` #### 解析 1. **初始化** 使用两个辅助结构体变量 `smallDummy` 和 `largeDummy` 来作为新链表的小于部分和大于等于部分的起始点。这样可以方便地构建两条独立的新链表。 2. **遍历原始链表** 对每一个节点判断其值是否小于给定的目标值 \(x\)。如果是,则将其链接至 `small` 链表;否则链接至 `large` 链表[^1]。 3. **拼接链表** 完成遍历后,将 `large` 的尾部设置为 `NULL`,防止形成循环链表。接着把 `small` 链表的尾部连接到 `large` 链表的头部,从而完成整个链表的重组[^2]。 4. **返回结果** 新链表的头部即为 `smallDummy.next`,因为这是所有小于 \(x\) 节点组成的链表起点[^3]。 --- ### 示例运行 假设输入如下: - 输入链表:\(1 \rightarrow 4 \rightarrow 3 \rightarrow 2 \rightarrow 5 \rightarrow 2\) - 参数 \(x = 3\) 执行上述代码后的输出将是: \[1 \rightarrow 2 \rightarrow 2 \rightarrow 4 \rightarrow 3 \rightarrow 5\] 这表明所有小于 \(x\) 的节点被移动到了前面,而其余节点保持原有顺序[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值