связанный список с разделителями
Описание вопроса
Учитывая односвязный список с головным узлом в качестве заголовка и целым числом k, разработайте алгоритм, позволяющий разделить связанный список на k последовательных частей.
Длина каждой части должна быть по возможности одинаковой: длина любых двух частей не должна отличаться более чем на 1. Это может привести к тому, что некоторые части станут нулевыми.
k частей должны быть расположены в том порядке, в котором они появляются в связанном списке, а длина первой части должна быть больше или равна длине последующей части.
Возвращает массив, состоящий из k частей, указанных выше.
Пример 1:
Входные данные: head = [1,2,3], k = 5
Выходные данные: [[1],[2],[3],[],[]]
Объяснение:
Выводится первый элемент output[0]. [0].val = 1, выход[0].next = ноль.
Последний элемент, выход[4], имеет значение NULL, но его строковое представление в виде ListNode равно [].
Пример 2:
Входные данные: head = [1,2,3,4,5,6,7,8,9,10], k = 3
Выходные данные: [[1,2,3,4],[5,6, 7],[8,9,10]]
Пояснение:
Входные данные разделены на несколько последовательных частей, длина каждой части отличается не более чем на 1. Длина передней части больше или равна длине задней части.
Совет:
количество узлов в связанном списке находится в диапазоне [0, 1000]
0 <= Node.val <= 1000
1 <= k <= 50
разделить связанный список
Вопрос требует разделения данного связанного списка на kkk последовательные части. Поскольку длина каждой разделенной части связана с длиной исходного связанного списка, необходимо сначала пройти по связанному списку, чтобы получить длину nnn связанного списка.
Получив длину n связанного списка, запишите частное = ⌊n / k⌋, остаток = n % k. Затем среди k разделенных частей длина первых оставшихся частей равна частному + 1, а длина каждой оставшейся части часть — это частное.
При разделении связанного списка начните обход с головного узла связанного списка, запомните текущий узел как curr и выполните следующие операции для каждой части:
- Используйте curr в качестве головного узла текущей части;
- Вычислить длину текущей детали partSize;
- Переместите curr назад на шаг partSize, тогда curr станет конечным узлом текущей части;
- Когда curr достигает конечного узла текущей части, необходимо разделить связь между curr и следующим узлом, а перед разделением необходимо сохранить следующий узел curr;
- Пусть следующий указатель curr указывает на нуль, чтобы завершить разделение curr и next;
- Назначьте рядом с curr.
демо-код
/**
* 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) {
int n = 0;
ListNode temp = head;
while (temp != null) {
n++;
temp = temp.next;
}
int quotient = n / k, remainder = n % k;
ListNode[] parts = new ListNode[k];
ListNode curr = head;
for (int i = 0; i < k && curr != null; i++) {
parts[i] = curr;
int partSize = quotient + (i < remainder ? 1 : 0);
for (int j = 1; j < partSize; j++) {
curr = curr.next;
}
ListNode next = curr.next;
curr.next = null;
curr = next;
}
return parts;
}
}