分隔链表(力扣第725题)

题目:

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

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

示例:

输入: 
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, 它代表了最后一个部分为空链表。

分析:

  这个题最核心的部分就是根据k值与给定链表之间长度的比较结果,这里以length作为给定链表的长度选择对应的处理方式:

  k >= length时,结果数组的前length填写链表中的元素,每个数组元素都是单个的链表的结点,数组中剩下的值都为null

  k < length时,需要对链表的元素进行分组,此时结果数组的大小是固定的,即为k,那么我们需要将length个链表元素分成k组,而且要求任意两个部分长度差至多为1,并且是这k个部分是连续的,那可以这么做,首先先给每个部分分配相同数量指标,然后还会有剩余的数量指标,剩余的数量一定是小于k的,因为 length%k < k,那么根据任意两个部分长度差不能超过1的原则,就将这未分配的剩余数量指标,从左到右依次分配给每个部分,一个部分多出一个元素。每个部分的数量如下:

  length/k + 1,length/k + 1,length/k + 1,……,length/k   (加1的是前length%k个部分)

代码实现:

public ListNode[] splitListToParts(ListNode root, int k) {
        ListNode[] res = new ListNode[k];
        if (root == null){
            
            for (int i = 0; i < k; i++) {
                res[i] = null;
            }
            return res;
        }
        ListNode p = root;
    
        int length = 0;
        while (p != null){
            
            length++;
            p = p.next;
        }
        p = root;
        if (k >= length){

            for (int i = 0; i < length; i++) {
                
                res[i] = new ListNode(p.val);
                p = p.next;
            }
        }else {
            int[] part_nums = new int[k];
            Arrays.fill(part_nums,length/k);

            for (int i = 0; i < (length % k); i++) {
                part_nums[i] = part_nums[i] + 1;
            }
            p = root;
            for (int i = 0; i < part_nums.length; i++) {

                ListNode node = new ListNode(-1);
                ListNode q = node;
                for (int j = 0; j < part_nums[i]; j++) {
                    
                    ListNode node1 = new ListNode(p.val);
                    node1.next = q.next;
                    q.next = node1;
                    q = q.next;
                    p = p.next;
                }
                res[i] = node.next;
            }
        }
        return res;
    }

我的代码有点垃圾,所以参考了cyc2018,我俩的思路是一样的,但是他在实现上彰显了大神的功力,即直接将原有的链表分隔成结果数组中的每个部分,学习一下:

public ListNode[] splitListToParts(ListNode root, int k) {
     int N = 0;
    ListNode cur = root;
    while (cur != null) {
        N++;
        cur = cur.next;
    }
    int mod = N % k;
    int size = N / k;
    ListNode[] ret = new ListNode[k];
    cur = root;
    for (int i = 0; cur != null && i < k; i++) {
        ret[i] = cur;
        int curSize = size + (mod-- > 0 ? 1 : 0);
        for (int j = 0; j < curSize - 1; j++) {
            cur = cur.next;
        }
        ListNode next = cur.next;
        cur.next = null;
        cur = next;
    }
    return ret;
    }

参考:

https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode%20%E9%A2%98%E8%A7%A3%20-%20%E9%93%BE%E8%A1%A8.md#9-%E5%88%86%E9%9A%94%E9%93%BE%E8%A1%A8

posted @ 2020-07-30 11:22  有心有梦  阅读(141)  评论(0编辑  收藏  举报