分隔連結串列(力扣第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;
}
參考: