725. 分隔链表
给你一个头结点为 head 的单链表和一个整数 k ,请你设计一个算法将链表分隔为 k 个连续的部分。
每部分的长度应该尽可能的相等:任意两部分的长度差距不能超过 1 。这可能会导致有些部分为 null 。
这 k 个部分应该按照在链表中出现的顺序排列,并且排在前面的部分的长度应该大于或等于排在后面的长度。
返回一个由上述 k 部分组成的数组。
示例 1:
输入:head = [1,2,3], k = 5
输出:[[1],[2],[3],[],[]]
解释:
第一个元素 output[0] 为 output[0].val = 1 ,output[0].next = null 。
最后一个元素 output[4] 为 null ,但它作为 ListNode 的字符串表示是 [] 。
示例 2:
输入: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 <= 10001 <= k <= 50
分配数量,按需截取
思路
兄弟们,冲冲冲,做(gan)下(掉)这道题(di)目(jun)
由题目可得:
- 我们要将链表分割成k个链表
- 任意两个子链表长度相差不超过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
};