开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情
725. 分隔链表
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/sp…
给你一个头结点为 head 的单链表和一个整数 k ,请你设计一个算法将链表分隔为 k 个连续的部分。
每部分的长度应该尽可能的相等:任意两部分的长度差距不能超过 1 。这可能会导致有些部分为 null 。
这 k 个部分应该按照在链表中出现的顺序排列,并且排在前面的部分的长度应该大于或等于排在后面的长度。
返回一个由上述 k 部分组成的数组。
示例 1:
输入:head = [1,2,3], k = 5 输出:[[1],[2],[3],[],[]] 解释: 第一个元素 output[0] 为 output[0].val = 1 ,output[0].next = null 。 最后一个元素 output[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
解法
首先在理解的时候可以将单链表题看成是列表题,简化成就是将一个列表分成均匀k段,如果不能被均匀平分的话,尽可能分配均匀一点,子列表长度相隔不超过1,类似于之前的题目,求得多余的m个,表明前m个的长度都是均匀长+1。 这题是单链表,结果主要是将单链表的表头加入结果表,再将满足链表的长度后进行截断。
- python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def splitListToParts(self, head: ListNode, k: int) -> List[ListNode]:
listLength = 0
p = head
while p:
listLength += 1 # get listNode length
p = p.next
avg_length = listLength // k # avg length
per_add_length = listLength % k # mul length
res = [None for _ in range(k)] # init res because should be devide into k nums listNode
p = head
for i in range(k):
if p == None:
break
curNum = avg_length + (1 if per_add_length > i else 0) # current num nodes in i listNode
res[i] = p # listNode head
for _ in range(curNum-1): # 0~curNum-1 not include curNum-1 for the reson res[i] = p
p = p.next # traverse
if p: # cut by set p.next = None
p_next = p.next
p.next = None
p = p_next
return res
- c++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
vector<ListNode*> splitListToParts(ListNode* head, int k) {
int n = 0;
ListNode * temp = head;
while(temp != nullptr)
{
n += 1;
temp = temp -> next;
}
int quotient = n / k;
int remainder = n % k;
vector<ListNode*> parts(k, nullptr);
ListNode *curr = head;
for(int i=0; i<k; i++)
{
if(curr == nullptr)
{
break;
}
parts[i] = curr;
int partSize = quotient + (i < remainder ? 1 : 0);
for (int j = 1; j<partSize; j++) // j从1开始
{
curr = curr->next;
}
if (curr)
{
ListNode *next = curr->next;
curr->next = nullptr;
curr = next;
}
}
return parts;
}
};
复杂度分析
- 时间复杂度:O(n) 其中 n 是链表的长度。需要遍历链表两次,得到链表的长度和分隔链表。
- 空间复杂度:O(1) 只使用了常量的额外空间,返回值不计入空间复杂度。