[前端]_一起刷leetcode 725. 分隔链表

480 阅读2分钟

大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。

题目

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 <= 1000
  • 1 <= k <= 50

思路

  1. 先经过一轮遍历,统计出链表的长度count;
  2. 新建一个长度为k的数组result = new Array(k),记录我们要返回的结果;
  3. 对数组进行填充,每个数组的链表长度最少为Math.floor(count / k),然后前面count % k个元素,每个长度加一。主要意思是,如果有8个元素,要分成3份,那么每个元素一开始初始长度都是2,这时候还残留2个待分配的节点,就在数组的前两位各加一;
  4. 通过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;
    });
};

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。