这递归和回溯在LeetCode中是如何工作的?

huangapple go评论80阅读模式
英文:

How does this recursion and back tracking work in LeetCode?

问题

这个函数会倒序打印链表的节点:

void recur(ListNode head) {
    if (head == null) return;
    recur(head.next);
    tmp.add(head.val);
}

如果链表是 1 -> 2 -> 3,那么 tmp(一个 ArrayList)会添加节点的值。

最后,通过打印 tmp,我们可以得到一个列表 [3, 2, 1]。然而,我不知道为什么它能够正常工作。为什么 recur 函数会循环到最后一个节点,然后倒序添加值呢?

英文:

This function which will print the nodes of a linked list in reverse:

void recur(ListNode head) {
	if(head == null) return; 
	recur(head.next);
	tmp.add(head.val);
}

If the list is 1 -> 2 -> 3 then tmp (an ArrayList) will add the value of the node.

At last, we can get a list [3, 2, 1] via printing tmp. However, I do not know why it works. Why does the recur function loop to the last node then add the values in reverse order?

答案1

得分: 1

我认为这个流程图可能对你有所帮助。

如图所示,当链表末尾被达到时,head.value 被添加到 tmp 列表中。也就是说,head 变为 null。

英文:

I think this flow diagram may help you.

这递归和回溯在LeetCode中是如何工作的?

As you can see from the diagram the head.value is added to the tmp list only when end of the linked list is reached. i.e . head becames null

答案2

得分: 0

代码部分已翻译完成,如下所示:

void recur(ListNode head) {
    if (head == null) return;
    tmp.add(head.val);
}
  1. 在第一步中,头部指向值为 1,这个条件检查 if (head == null) 将返回 false,因为头部节点不是空的。
  2. 然后我们调用相同的函数 recur,但是针对值为 2 的下一个节点,执行 recur 重新开始,但是以节点 2 作为头部节点。我们再次检查 if (head == null) -> false,同样的原因,这里头部不是空的。
  3. 然后我们调用相同的函数 recur,但是针对下一个节点,这个节点是空的 head.next -> null,因为在节点 2 之后没有节点了。我们检查 if (head == null),但是现在我们有了 true,表示当前节点,意味着没有节点留在后面,我们不能继续调用 recur()。因此,我们用 return 语句停止递归。
  4. 现在,我们再次返回到步骤#2并继续执行,因为 recur(head.next) 的执行通过 return 语句结束。这意味着,这个节点是最后一个节点,我们将其值放入 tmp。并且 recur 对于 ListNode 2 的执行结束了,因为在此之后没有代码行了。
  5. 现在,我们再次返回到步骤#1,并按照步骤4中描述的相同逻辑进行。由于节点 2recur 执行结束,我们继续执行并将值 1 放入 tmp 数组中。

if (head == null) - 这个检查被称为递归的“基本情况”,意思是“何时需要结束执行并退出?”如果没有它,递归将无限地进行下去。

我们深入到 ListNode 的末尾,然后再次返回到顶部。
为了能够将 ListNode 的值放入 tmp 中,我们首先需要将下一个值放入 tmp,依此类推。

我希望我解释得更准确,现在对您更加清晰。

英文:

It's pretty much simple, let's consider the [1 -> 2] node with two ListNode and we want to reverse with you function:

void recur(ListNode head) {
    if (head == null) return;
    recur(head.next);
    tmp.add(head.val);
}
  1. On the first stem, the head will point to 1 value, this check if (head == null) will return false since head node is not null.
  2. Then we call the same function recur but for the next node with value 2, and execution of recur start over but with node 2 as a head node. We again check if (head == null) -> false, same reason, head is not null here.
  3. Then we call the same function recur but for the next node which is null head.next -> null, since there are no nodes anymore after node 2. We check if (head == null), but now we have true, the current node, meaning there are no nodes left after and we can't go further calling recur() again. So, we stop the recursion with a return statement.
  4. Now, we return again to step #2 and continue execution, because the execution of recur(head.next) ends by return statement. That means, this node is the last one, and we put its value to the tmp. And the execution of recur for ListNode 2 ends, since there are no code lines after.
  5. Now, we return again to step #1 and do the same logic as described in step 4. Since recur for node 2 ends its execution we proceed and put value 1 to tmp array.

if (head == null) return; - this check, called recursion base case, meaning when we need to end execution and exit?, without it recursion will go infinitely.

We dig to the end of the ListNode and then return again to the top.
To be able to put ListNode value to the tmp we need first put next value to the tmp and so on.

I hope, I explained more accurately and its more clear for you now.

huangapple
  • 本文由 发表于 2020年4月10日 18:06:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/61138015.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定