分隔链表(力扣第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;
}
参考: