java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 |
---|
解题思路 |
---|
- 首先获取链表长度,假设是10,让我们分3块
- 然后获取每块应该分多少块,quotient = 10/3 = 3个,然后获取平均分完后,还剩几块remainder = 10%3 = 1个。
- 题目要求各块之间长度差距不能超过1,所以remainder中多余的,我们每块匀一个。
- 为什么一定可以匀一个,匀完呢?因为我们是10%3,我们要分3大块,剩下的不够平均给这3大块才剩下的。所以它一定小于块数。 因此每块分一个它都不够分。
- 另外,链表它是一个结点连着一个结点的。题目要求分块,那么分块后的结点就不能继续连着了,所以还需要把每块末尾的结点的next置为null。
代码:时间复杂度O(n) 空间复杂度O(1) |
---|
/**
* 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) {
/****第一步,先遍历一遍链表,获取链表长度 */
ListNode current = head;
int count = 0;
while(current!=null){
count++;
current=current.next;
}
/***第二步,算出分k块时,每块应该分多少记录到quotient,如果除不开(没法正好分完,有剩余),
就记录到remainder,因为是除不开留下的,肯定比k小,所以,多余的remainder这些
只需要前面每块匀一个即可,因为题目要求,块与块之间元素个数差,不能大于1个,所以多余的,每个块只能匀一个 */
ListNode[] listNodes = new ListNode[k];//题目要求的答案数组
current = head;//current继续充当遍历指针
int quotient = count/k;//每块分多少
int remainder = count%k;//剩多少,remainder绝对会比块数少,所以多出来的,我们在前面的块中,每块分一个
/***第三步, 每块分quotation个,另外如果remainder有剩余,只能给当前块匀一块
另外,每块分完结点后,这块末尾的结点的next要置为null,否则它会连着其它结点,无法判断分块点在哪*/
for(int i = 0;i < k && current!=null;i++){
listNodes[i] = current;//让当前块,指向current
// int partSize = quotient + (remainder>0?1:0); remainder--;//因为这样写需要两行代码,下面这种只需要一行代码,效果相同
int partSize = quotient + (i < remainder?1:0);//如果还有多余的块,就给当前块多分一块,否则多分0块
for(int j = 1;j<partSize;j++) current = current.next;//找到当前块的末尾结点,方便我们将分块点.next置为null
ListNode next = current.next;//记录current的next,放置置为null后,next丢失
current.next = null;//让current的next为null,否则一直连着后面的,就不知道哪块是哪块了
current = next;//然后current指向next,继续遍历
}
return listNodes;//返回答案数组
}
}