题目
题目解析
题目大意:就是将一个链表,分隔成 k 个部分,且每个部分 都是按照原先链表的节点顺序。
如果链表节点个数 n 小于 k,那么,也就是说 链接节点 不够分,无法做到每一个部分都可以分到一个节点。
我们再来看下题目例子:
由此,我们得出一个结论:链表节点个数 n 小于 k的情况,保证 前 n 个 部分( n < k),都可以分到一个,后面的不管,让它为空。
但是! 根据题目示例2
我们还可以得出一个结论 : 题目要求 链表分为 k 个 部分,就比如示例2,链表有 n(10) 个节点,被要求 分成 k (3)个部分,此时 每个部分至少获得 3(n / k) 个节点,多出节点 (n%k) 将会被分配到几个部分。
但是!需要注意 多出节点,不是在分配完节点后,再给予。而是:在计算出每个部分至少获得的节点个数的时候,将其加上。到了真正给每个部分,分配节点的时候,就按照这个结果去分配
代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode[] splitListToParts(ListNode head, int k) {
int n = 0;
ListNode tmp = head;// tmp 用来 代替 head,遍历脸表获取节点个数
while(tmp != null){
n++;
tmp = tmp.next;
}
// quotient - 商
int quotient = n / k; // 计算 每部分 至少获得多少个节点
// remainder - 余数
int remainder = n % k; // 计算 :每个部分获得了相同的节点个数后,链表剩余的节点个数
ListNode[] parts = new ListNode[k];// 链表数组,每个元素 都是一个链表的头节点
ListNode cur = head;// 遍历链表,辅助将链表分成k部分
for(int i = 0; i < k && cur != null; i++){
parts[i] = cur;// 赋予 该部分的头节点
// 这里就是 将 多出节点个数,在真正分配节点之前,赋给前几个部分,前几个部分都将获得 1 个节点。
// 就是 多出 m 个节点,将其分给 m 个部分,即每部分会分到一个节点。
int partSize = quotient + (i < remainder ? 1 : 0);
for(int j = 1; j < partSize; j++){// 给每个部分 分配节点
cur = cur.next;
}
ListNode next = cur.next;
cur.next = null;// 每个部分获得的节点所形成的链表,都是一个单独的链表
cur = next;// 为下一次 分配 节点做准备挨
}
return parts;
}
}
代码细节
细节一:
细节二
细节三(挖掘细节一)
总结
当我们看到这道题的时候,我们就要想,你不是要分成 k 个部分吗?那么,每个部分分多少个【quotient】,计算出每个部分 的 分配个数之后,会不会有 多余节点【remainder】。(这两个代码出来了)
然后,计算这两个值,为此,我们需要链表的节点个数。(这就又写了一块代码)
And,题目需要我们返回 节点数组 ListNode[],那么。我们是不是要创建一个?再加上它要把链表分成 k 个部分。这容量是不是就确定了?【 ListNode[] parts = new ListNode[k];未赋值,每个元素的初始化为 null】
最后,我们要去遍历链表,根据我们计算出的每个部分最终分配节点数 partSize,去决定该部分所能分配的节点个数。【注意分配完,截断链表;且不要影响下一次分配节点】
这就是 这题完整的解题思维。