所以我有这个递归解决方案打印列表末尾的第n个元素:
void print_nth_from_last_rec(Node* node, int n) {
static int count { 0 };
if (!node) return;
print_nth_from_last_rec(node->next, n);
if (++count == n)
cout << node->data;
}
但我无法弄清楚如何使用递归返回该元素。有可能吗?
尝试:
如果我在Node*
时分配了静态(++count == n)
,我可以这样做:
Node* get_nth_from_last_rec(Node* node, int n) {
static int count { 0 };
static Node* ret{ nullptr };
if (node) {
get_nth_from_last_rec(node->next, n);
if (++count == n)
ret = node;
}
return ret;
}
也可以传入对out
节点的引用并为其指定第n个元素。
但是有更好的方法吗?这些静电对我来说看起来不太干净。
答案 0 :(得分:3)
Node* get_nth_from_last_rec(Node* node, int& n)
{
if (node)
{
Node* result = get_nth_from_last_rec(node->next, n);
if (result)
return result;
else if (! n--)
return node;
}
return nullptr;
}
答案 1 :(得分:3)
以下是我如何做到的(我希望从上下文中可以明显看出advance
做了什么):
Node* get_nth_from_last(Node* node, int n, Node *ahead = 0) {
if (ahead == 0) {
// might like to check for size < n at the same time
// and return something to indicate error in that case
ahead = advance(node, n);
}
if (ahead->next == 0) return node; // or whatever the end condition is
return get_nth_from_last(node->next, n, ahead->next);
}
如果要将该默认参数隐藏在远离调用者的位置,请使用辅助函数。它只需要效率,如果你想要真正慢的代码,那么没有它,并在每个递归步骤调用advance
。
你几乎不需要static
个变量来让你的递归工作。您始终可以使用默认值添加参数,或者使用额外参数编写辅助函数并调用它来执行所有工作。除了它们可能引起读者的任何混淆之外,它们使函数非线程安全,并且不可重入信号处理程序。
我的代码确实2 * len - n
节点前进,而你的代码只执行len
(加上n
个从递归中返回的工作。如果你想坚持你的表现特征但牺牲尾递归,那么这样的事情(我要么在这个问题上,或者在我的第一个回答中,取决于n
的含义...... ):
Node* get_nth_from_last_helper(Node* node, int &depth) {
if (node == 0) return 0;
Node *n = get_nth_from_last_helper(node->next, depth);
--depth;
return (depth == 0) ? node : n;
}
Node *get_nth_from_last(Node *node, int n) {
return get_nth_from_last_helper(Node *node, n);
}
答案 2 :(得分:0)
就我个人而言,我会使用从前面函数计数的第n个到0
Node* get_nth_from_first_rec(Node* node, int n) {
if (!node || n == 0) {
return node;
}
return get_nth_from_last_rec(node->next, n - 1);
}
并计算列表中的元素数量(如果需要,递归)
int get_list_length(Node* node) {
if (!node) {
return 0;
}
return 1 + get_list_length(node->next);
}
那么我可以将索引计算为第一个索引的第n个
Node* get_nth_from_last_rec(Node* node, int n) {
int count = get_list_length(node);
return get_nth_from_first_rec(node, n - count);
}
答案 3 :(得分:0)
在这里,我相信我有一种用Java解决它的简洁尾递归方式。
public static LinkedListNode findnthToLastRecursionHelper(LinkedListNode node, LinkedListNode last,int pos){
if(node==null) return null;
if(pos<1)
{
pos=1; //We have reached the nth iteration for last, now time to increment node and last together.
node = node.next;
if(last==null) return node;
}
else if(last==null) return null;
return findnthToLastRecursionHelper(node,last.next,--pos);
}
这是主要的尾递归块,它将last
指针移动到nth
位置,一旦到达位置,就会移动node
&amp; last
指针在一起。
public static LinkedListNode findnthToLastRecursion(LinkedListNode head,int pos){
return findnthToLastRecursionHelper(head,head.next,pos);
}
这是调用者的功能,以保持美观。