大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。
题目
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
思路
- 先经过一轮遍历,统计出链表的长度
count; - 新建一个长度为
k的数组result = new Array(k),记录我们要返回的结果; - 对数组进行填充,每个数组的链表长度最少为
Math.floor(count / k),然后前面count % k个元素,每个长度加一。主要意思是,如果有8个元素,要分成3份,那么每个元素一开始初始长度都是2,这时候还残留2个待分配的节点,就在数组的前两位各加一; - 通过
map方法把数字改成链表的节点即可。
实现
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode[]}
*/
var splitListToParts = function(head, k) {
// 一轮遍历计算出长度
let count = 0, cur = head;
while (cur) {
cur = cur.next;
count++;
}
// 结果中每个节点的长度
let result = new Array(k).fill(Math.floor(count / k));
// 平均分配完,有多的加到前面的节点
let over = count % k;
while (over > 0) {
result[over - 1]++;
over--;
}
// 根据各段的长度切割链表
return result.map(item => {
let newItem = head;
let cur = newItem;
// 一开始进来就是第一个节点了
while (item > 1) {
cur = cur && cur.next;
item--;
}
if (cur) {
const next = cur.next;
cur.next = null;
head = next;
}
return newItem;
});
};
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。