zoukankan      html  css  js  c++  java
  • 分隔链表(力扣第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, 
    oot.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

  • 相关阅读:
    从数据库表中查询日期最新的记录
    ArcGIS js api开发环境配置
    HRESULT:0x80070057 (E_INVALIDARG)
    ArcGIS js api三种查询功能
    sql设置字段默认值
    文件后缀与mime类型对应表
    关于dojo自定义类
    android用户登录验证
    java实现QQ互联登录
    springboot实现网站微信扫码登录
  • 原文地址:https://www.cnblogs.com/yxym2016/p/13402765.html
Copyright © 2011-2022 走看看