[路飞]_程序员必刷力扣题: 725. 分隔链表

141 阅读2分钟

725. 分隔链表

给你一个头结点为 head 的单链表和一个整数 k ,请你设计一个算法将链表分隔为 k 个连续的部分。

每部分的长度应该尽可能的相等:任意两部分的长度差距不能超过 1 。这可能会导致有些部分为 null 。

这 k 个部分应该按照在链表中出现的顺序排列,并且排在前面的部分的长度应该大于或等于排在后面的长度。

返回一个由上述 k 部分组成的数组。

示例 1: image.png

输入:head = [1,2,3], k = 5
输出:[[1],[2],[3],[],[]]
解释:
第一个元素 output[0] 为 output[0].val = 1 ,output[0].next = null 。
最后一个元素 output[4] 为 null ,但它作为 ListNode 的字符串表示是 []

示例 2:

image.png

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

提示:

  • 链表中节点的数目在范围 [0, 1000]
  • 0 <= Node.val <= 1000
  • 1 <= k <= 50

分配数量,按需截取

思路

兄弟们,冲冲冲,做(gan)下(掉)这道题(di)目(jun)

由题目可得:

  1. 我们要将链表分割成k个链表
  2. 任意两个子链表长度相差不超过1(这不就是均匀分配么)

这我们不就开始思考了吗,ding~,这思路不就来了

  • 均匀分配:那就是链表长度len除以坑位数量k,然后向下取整得到一个nums,那就是说每个子链表最少为nums个节点喽。
  • 当然不可能都刚好除尽,那就要取余了,然后最后结果res数组中比较靠前的一个分配一个呗,分完为止
  • 我们希望知道最后结果res中每个子链表的长度,我们可以直接去原链表中遍历截取

知道了最少个数nums,再判断一下余数yu还有没有值,有就拿过来一个算在我们总长度total中,让yu--(用完多余元素的就没啦)

  • 所以total = yu > 0 ? nums + 1 : nums

知道了子节点长度直接遍历链表,为了知道子链表的末尾,我们需要一个指针newHead,从头开始向后移动,因为一开始位置就已经在head上了,所以只需要再移动total-1次就可以了

遍历结束我们要判断一下我们的newHead:

  • 正常情况下,我们的newHead就已经指在当前子链表的末尾节点上了,处理一下newHead的指针next为null。处理完毕,我们就可以往res里面丢一个head头结点了,然后处理一下head的指针,让head从我们的newHead的下一位开始
  • 当前节点的total为0,那就是没有节点,那我们newHead不就只能指在空(null)上了吗,那就直接往res结果数组中丢一个null算啦

最后返回res结果,终于完了

var splitListToParts = function (head, k) {
    var res = []
    var p = head
    var len = 0
    while (p) {
        len++
        p = p.next
    }

    var yu = len % k
    var nums = (len - yu) / k

    while (res.length < k) {
        var total = yu > 0 ? nums + 1 : nums
        yu > 0 ? yu-- : ''
        var newHead = head
        while (total > 1) {
            newHead = newHead.next
            total--
        }
        if (newHead) {
            res.push(head)
            head = newHead.next
            newHead.next = null
        } else {
            res.push(null)
        }
    }
    return res
};