題目地址:
https://leetcode.com/problems/split-linked-list-in-parts/
給定一個鏈表,再給定一個數,要求將鏈表分爲儘可能長度相等的個部分,允許有空鏈表的存在,返回長度爲的以鏈表頭結點爲元素的數組,要求鏈表長度按照降序排列,並且相鄰鏈表的長度之差不大於。
爲了計算每個部分的長度,我們需要先知道原鏈表的長度,然後將其除以。如果正好能除盡,那麼顯然每個部分的長度就是,否則設餘數爲,那麼只需要讓前個鏈表長度爲,後面鏈表長度爲即可。
具體實現方面,可以設一個dummy節點,然後再用一個指針prev一開始指向dummy節點,每次先把prev.next加入最終結果,接下來要用一個臨時指針緩存一下prev的位置,然後讓prev向後走(或者步,看情況),接着利用臨時指針將上一個分離出來的鏈表的尾巴與原鏈表斷開。緩存的這一步是必要的,否則無法實現斷開的操作。代碼如下:
public class Solution {
public ListNode[] splitListToParts(ListNode root, int k) {
ListNode dummy = new ListNode(0);
dummy.next = root;
ListNode prev = dummy;
int length = len(root);
ListNode[] res = new ListNode[k];
int partLength = length / k, numOfLonger = 0;
// 如果無法分爲k等份,就算一下餘數r是多少,
// r的含義是一開始r個鏈表的長度需要等於length / k + 1
if (partLength * k != length) {
numOfLonger = length % k;
}
int ind = 0;
ListNode tmp = null;
for (int i = 0; i < numOfLonger; i++) {
res[ind++] = prev.next;
// 緩存prev的位置,以便後面斷開
tmp = prev;
// 讓prev向後走
for (int j = 0; j < partLength + 1; j++) {
prev = prev.next;
}
// 執行斷開操作
tmp.next = null;
}
for (int i = 0; i < k - numOfLonger; i++) {
res[ind++] = prev.next;
tmp = prev;
for (int j = 0; j < partLength; j++) {
prev = prev.next;
}
tmp.next = null;
}
return res;
}
// 求head爲頭的鏈表長度
private int len(ListNode head) {
int l = 0;
while (head != null) {
head = head.next;
l++;
}
return l;
}
}
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
時間複雜度,空間。