题目:
给定一个头结点为 root 的链表, 编写一个函数以将链表分隔为 k 个连续的部分。
每部分的长度应该尽可能的相等: 任意两部分的长度差距不能超过 1,也就是说可能有些部分为 null。
这k个部分应该按照在链表中出现的顺序进行输出,并且排在前面的部分的长度应该大于或等于后面的长度。
返回一个符合上述规则的链表的列表。
举例: 1->2->3->4, k = 5 // 5 结果 [ [1], [2], [3], [4], null ]
思路:
通过分析可知:
-
如果k大于链表长度length,那么返回的数组的前length项的每个链表都只有一个结点,后面的 length+1 ~ k 项元素都是null;
如1->2->3, k = 5,length = 3 ,则返回的数组中前3(length)个元素中的结点个数都是1个,4~5的数组索引中元素都为null。
-
如果k小于链表长度length,那么返回的数组可以分成2个部分,前(length%k)项每个数组元素的链表中的结点数为 (length / k) + 1,后一部分的每个数组元素中的结点个数为(length/k)。
如1->2->3->4->5,k = 2,length = 5;length / 2 = 2;length % 2 = 1。即返回的数组的前一部分(数组索引为1)有2+1个结点;后一部分(数组索引为1+1)有2个结点。
参考代码:
**打扫房间*
public static ListNode[] splitListToParts(ListNode root, int k) {
//** 注意root == null时是返回数组大小为k的null数组**//
if(root == null || k <= 1)return new ListNode[k];
//求链表的长度
ListNode p = root;
ListNode q;
ListNode r;
int length = 0;
while(p != null){
length ++;
p = p.next;
}
ListNode[] listNode = new ListNode[k];
//k>length,数组分成2部分,前length个元素中结点数为1,后一部分元素为null
if(k > length){
p = root;
q = p;
//前面k个数组元素都存一个节点
for(int i = 0; i < length; i++){
q = p.next;
p.next = null;
listNode[i] = p;
p = q;
}
}
//k<length,分成2部分,前length%k个元素中有length/k+1个结点,后一部分每个元素有length/k个元素
else{
int m = length % k;
int n = length / k;
p = root;
q = root;
//前m个链表有n+1结点,后边的链表都有n个结点
int i = 0;
while(p != null){
//r记录头结点
r = p;
if(i < m){
for(int j = 0; j < n;j++)p = p.next;
}
else{
r = p;
for(int j = 0; j < n - 1; j++)p = p.next;
}
q = p.next;
p.next = null;
p = q;
listNode[i] = r;
i++;
}
}
return listNode;
}
小结:
该题思路不难去想,但是在做的过程中还是要思路清晰,要把该注意的细节注意到。