如何在 C++ 中递归拆分 k 个节点后的链表?
How to recursively split a linked list after k nodes in C++?
我有一个普通链表:
struct node{
int info;
node* next;
};
我需要编写一个递归函数,将在 k 个元素之后通过引用传递的给定链表分成 2 个,将前 k 个节点留在该列表中,return将第二个列表与其余的节点。
我的迭代解决方案如下所示:
node* split(node*&L, int k){
node* M;
node* head = L;
while(k>1){
head=head->next;
k--;
}
M = head->next;
head->next = NULL;
return M;
}
Output:
L: 1 2 3 4 5 6
after split with: k = 3
L: 1 2 3
M: 4 5 6
这似乎工作得很好。现在我真的想不出一个递归的解决方案。我正在尝试:
node* splitL(node*&L, int k){
if(!L) return 0;
if(k<=1){
node* x = L->next;
L->next = NULL;
return x;
}
L->next = splitL(L->next, k-1);
return L;
}
这显然是错误的,因为它 returning x 到 L->next 所以两个列表都变成 1 2 3 4 5 6.
如何为此编写递归函数?参数和 return 类型应该保持不变。如果有人可以解释我如何将我的迭代解决方案转换为递归解决方案,那也很棒。
您目前有
node* split(node*&L, int k){
node* M;
node* head = L;
while(k>1){
head=head->next;
k--;
}
M = head->next;
head->next = NULL;
return M;
}
你想要这样的东西
node* split(node*&L, int k){
node* M;
node* head = splitPoint(L, k);
M = head->next;
head->next = NULL;
return M;
}
node* splitPoint(node*&L, int k){
if (k <= 0)
return L;
return splitPoint(L->next, k - 1);
}
注意这个和你原来的守卫 k
大于列表的长度。
单功能版:
node* split(node*&L, int k){
if (k <= 0)
{
node* head = L;
node* M = head->next;
head->next = NULL;
return M;
}
return split(L->next, k - 1);
}
起初我没有看到通过引用传递列表指针的意义,但后来我发现它是实现的关键。
我认为你可以这样做:
- 检查空输入列表;可能是要求您将输入列表拆分到超出其末尾的位置 (
k > list size
)。
- 检查
k == 0
;这是进行拆分的要点,因此 1) return 当前 head
和 2) 将前一个节点的 next
指针设置为空(如果这是第一次调用,则设置列表指针本身);您只需将 head
设置为 null,因为 head
是对您在调用 split_list
. 时使用的指针的引用
- 否则,递归调用
split_list
。
node* split_list(node*& head, int k)
{
if (!head) { return nullptr; }
if (k == 0) { node* ret{head}; head = nullptr; return ret; }
return split_list(head->next, k-1);
}
我有一个普通链表:
struct node{
int info;
node* next;
};
我需要编写一个递归函数,将在 k 个元素之后通过引用传递的给定链表分成 2 个,将前 k 个节点留在该列表中,return将第二个列表与其余的节点。
我的迭代解决方案如下所示:
node* split(node*&L, int k){
node* M;
node* head = L;
while(k>1){
head=head->next;
k--;
}
M = head->next;
head->next = NULL;
return M;
}
Output:
L: 1 2 3 4 5 6
after split with: k = 3
L: 1 2 3
M: 4 5 6
这似乎工作得很好。现在我真的想不出一个递归的解决方案。我正在尝试:
node* splitL(node*&L, int k){
if(!L) return 0;
if(k<=1){
node* x = L->next;
L->next = NULL;
return x;
}
L->next = splitL(L->next, k-1);
return L;
}
这显然是错误的,因为它 returning x 到 L->next 所以两个列表都变成 1 2 3 4 5 6.
如何为此编写递归函数?参数和 return 类型应该保持不变。如果有人可以解释我如何将我的迭代解决方案转换为递归解决方案,那也很棒。
您目前有
node* split(node*&L, int k){
node* M;
node* head = L;
while(k>1){
head=head->next;
k--;
}
M = head->next;
head->next = NULL;
return M;
}
你想要这样的东西
node* split(node*&L, int k){
node* M;
node* head = splitPoint(L, k);
M = head->next;
head->next = NULL;
return M;
}
node* splitPoint(node*&L, int k){
if (k <= 0)
return L;
return splitPoint(L->next, k - 1);
}
注意这个和你原来的守卫 k
大于列表的长度。
单功能版:
node* split(node*&L, int k){
if (k <= 0)
{
node* head = L;
node* M = head->next;
head->next = NULL;
return M;
}
return split(L->next, k - 1);
}
起初我没有看到通过引用传递列表指针的意义,但后来我发现它是实现的关键。
我认为你可以这样做:
- 检查空输入列表;可能是要求您将输入列表拆分到超出其末尾的位置 (
k > list size
)。 - 检查
k == 0
;这是进行拆分的要点,因此 1) return 当前head
和 2) 将前一个节点的next
指针设置为空(如果这是第一次调用,则设置列表指针本身);您只需将head
设置为 null,因为head
是对您在调用split_list
. 时使用的指针的引用
- 否则,递归调用
split_list
。
node* split_list(node*& head, int k)
{
if (!head) { return nullptr; }
if (k == 0) { node* ret{head}; head = nullptr; return ret; }
return split_list(head->next, k-1);
}