二进制树木遍历 - 递归

发布于 2025-01-24 05:06:07 字数 818 浏览 0 评论 0 原文

在下面写下了leetcode问题的解决方案 -

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    
    def inorderTraversal(self, root: Optional[TreeNode],traversal_list = []) -> List[int]:

        if root:
            traversal_list= self.inorderTraversal(root.left,traversal_list)
            traversal_list.append(root.val)
            traversal_list = self.inorderTraversal(root.right, traversal_list)
        return traversal_list
    

从示例问题1返回[1,3,2]的正确解决方案。 示例问题2:[]再次返回[1,3,2]。

为什么答案#1被带到问题2?

Wrote below solution to a leetcode problem https://leetcode.com/problems/binary-tree-inorder-traversal/-

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    
    def inorderTraversal(self, root: Optional[TreeNode],traversal_list = []) -> List[int]:

        if root:
            traversal_list= self.inorderTraversal(root.left,traversal_list)
            traversal_list.append(root.val)
            traversal_list = self.inorderTraversal(root.right, traversal_list)
        return traversal_list
    

Returns correct solution of [1,3,2] from example question #1.
Returns [1,3,2] AGAIN from example question #2: [ ].

Why is answer #1 getting carried over to question #2?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云裳 2025-01-31 05:06:07

不要修改参数的默认值

leetcode提供的模板 -

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:

代码的问题在这里 -

  1. 您添加了第三个参数, traversal_list ,默认值为<代码> []
  2. 在代码的非恢复分支中,对此列表的引用
  3. 在递归分支中返回, traversal_list .append 突变
class Solution:
    # ⚠️ 1
    def inorderTraversal(self, root: Optional[TreeNode],traversal_list = []) -> List[int]:
        if root:
            traversal_list= self.inorderTraversal(root.left,traversal_list)
            traversal_list.append(root.val) # ⚠️ 3
            traversal_list = self.inorderTraversal(root.right, traversal_list)
        return traversal_list # ⚠️ 2

reteation the问题

这意味着随后调用解决方案#inordertraversal 将包含一个预处理的 traversal_list ,并导致错误的答案。您可以在下面的问题中看到最小的娱乐 -

def foo (x = []):
  x.append(1)
  return x
print(foo()) # [1]
print(foo()) # [1, 1] # ❌

在另一个示例中,查看如何评估默认参数值 执行脚本时 -

def hello():
  print(1)
  return 3

def foo (x = hello()):  # ⚠️ hello() happens first
  return x

print(2)                # ⚠️ this is actually second!
print(foo())
1
2
3

修复修复

修复它删除第三个参数, traversal_list 。没有必要。只需返回 [] 当不存在 root 时 -

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if root:
            left = self.inorderTraversal(root.left)
            right = self.inorderTraversal(root.right)
            return left + [root.val] + right # ✅
        else:
            return [] # ✅

编写此书的改进方法是在类外编写遍历函数 -

def inorder(t):
if t:
yield from inorder(t.left) # ⚙️
yield t.val #

don't modify a parameter's default value

The template provided by LeetCode -

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:

The problem with your code is here -

  1. You added a third parameter, traversal_list, with a default value of []
  2. In the non-recursive branch of the code, a reference to this list is returned
  3. In the recursive branch, traversal_list is mutated with .append
class Solution:
    # ⚠️ 1
    def inorderTraversal(self, root: Optional[TreeNode],traversal_list = []) -> List[int]:
        if root:
            traversal_list= self.inorderTraversal(root.left,traversal_list)
            traversal_list.append(root.val) # ⚠️ 3
            traversal_list = self.inorderTraversal(root.right, traversal_list)
        return traversal_list # ⚠️ 2

recreation of the problem

This means subsequent calls to Solution#inorderTraversal will contain a prepopulated traversal_list and result in an incorrect answer. You can see a minimal recreation of the problem in below -

def foo (x = []):
  x.append(1)
  return x
print(foo()) # [1]
print(foo()) # [1, 1] # ❌

In another example, look how the default parameter value is evaluated only once when the script is executed -

def hello():
  print(1)
  return 3

def foo (x = hello()):  # ⚠️ hello() happens first
  return x

print(2)                # ⚠️ this is actually second!
print(foo())
1
2
3

fix it

To fix it, remove the third parameter, traversal_list. There's no need for it. Simply return [] when root is not present -

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if root:
            left = self.inorderTraversal(root.left)
            right = self.inorderTraversal(root.right)
            return left + [root.val] + right # ✅
        else:
            return [] # ✅

An improved way to write this is to write a traversal function outside of the class -

def inorder(t):
  if t:
    yield from inorder(t.left)  # ⚙️
    yield t.val                 # ????
    yield from inorder(t.right) # ⚙️
class Solution:
  def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    return list(inorder(root)) # ????

"what if i want to use append?"

If you absolutely want to use .append, you can model the solution above in a similar way.

def inorder(root):
  output = [] # ????
  def traverse(t):
    if t:
      traverse(t.left)     # ⚙️
      output.append(t.val) # ???? + ????
      traverse(t.right)    # ⚙️
  traverse(root)
  return output # ????
class Solution:
  def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    return inorder(root) # ????

not a universal behavior

Note this behaviour is in direct contrast to other languages. For example, JavaScript will re-evaluate a parameter's default value each time the function is run -

function foo(x = []) {
  x.push(1)
  return x
}

console.log(foo()) // [1]
console.log(foo()) // [1] ???? differs from python's behaviour

function hello() {
  console.log(1)
  return 3
}

function foo(x = hello()) {
  return x
}

console.log(2)
console.log(foo())

2
1  // ???? differs from python's behaviour
3
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文