【问题标题】:Can't figure out how to stop returning list inside of list (leetcode problem)无法弄清楚如何停止在列表中返回列表(leetcode 问题)
【发布时间】:2020-11-16 06:08:15
【问题描述】:

返回列表内的列表(不需要)

我不断返回列表中的列表,用于以下 LeetCode 问题257. Binary Tree Paths,这不是问题想要的。我在解决遍历问题时似乎总是遇到这个问题。

这是我当前的解决方案及其输出。

# 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 binaryTreePaths(self, root: TreeNode, val: str="") -> List[str]:
        if not root:
            return ""
        val += str(root.val) + "->"
        if not root.left and not root.right:
            return val[:-2]
        return [path for path in [self.binaryTreePaths(root.left, val), self.binaryTreePaths(root.right, val)] if path]

输入: [1,2,3,null,5]

输出: [["1->2->5"],"1->3"]

预期: ["1->2->5","1->3"]

我尝试过的事情

  1. 创建 res 变量并使用 res.extend()
res = []
res.extend(path for path in [self.binaryTreePaths(root.left, val), self.binaryTreePaths(root.right, val)] if path)
  1. 使用附加而不是扩展以及条件来尝试过滤掉不需要的元素。

我在解决遍历问题时经常遇到这个问题,所以如果这里有人有解决方案以及一些关于如何培养对这里出了什么问题的直觉以及如何在未来,我将非常感谢您的帮助。

编辑

好吧,我一直在努力尝试修复我的解决方案,大约 20 分钟后,我想出了以下可憎的事情。

class Solution:
    def binaryTreePaths(self, root: TreeNode, val: str="") -> List[str]:
        if not root:
            return ""
        val += str(root.val) + "->"
        if not root.left and not root.right:
            return val[:-2]
        r1 = self.binaryTreePaths(root.left, val)
        r2 = self.binaryTreePaths(root.right, val)
        if isinstance(r1, str):
            r1 = [r1]
        if isinstance(r2, str):
            r2 = [r2]
        for i in r1:
            if i == "":
                r1.pop(r1.index(i))
        for i in r2:
            if i == "":
                r2.pop(r2.index(i))
        return r1 + r2

我对我的解决方案一点也不满意,所以如果您知道更干净的解决方案,请继续发布您的解决方案/建议。

【问题讨论】:

  • binaryTreePaths 返回一个列表,所以 return [path for path in [self.binaryTreePaths]] 返回一个列表内的列表。使用itertools.chain
  • 当您返回列表时,问题就开始了。

标签: python python-3.x list return


【解决方案1】:

根本问题是binaryTreePaths 函数根据条件返回不同的类型。如果 root 是假的或者没有 left 或 right 集合,它只返回一个字符串(""val[:-2]),但在所有其他情况下它返回一个列表。

该列表仅在第一级回归时需要(当将最终值返回给调用者时),但它的设置方式也可以从任何递归级别返回一个列表。因此,任何同时满足返回列表推导的条件的递归都将在较低递归级别的列表中结束。

因此,当您旅行多个节点时,它将被包含在每个附加节点的列表中。因此,"1->3" 不在列表中,因为它在右侧第一次递归后立即作为字符串返回,但 "1->2->5" 在列表中,因为在返回字符串之前有一个额外的递归级别。

有多种方法可以解决此问题 - 例如,您可以跟踪回归级别并仅使用 1 以上任何深度的左/右字符串进行响应,然后仅从级别 1 返回列表。或者您可以有一个处理第一层的父函数和一个执行递归部分的辅助函数(可能是其中的一个子函数)。

一半的乐趣在于弄清楚 - 所以我把代码片段留给你。希望这为您提供了自己解决问题的工具(根据您问题的后半部分)。关键是在每个递归级别准确地构造返回值。实时执行此操作的最佳方法是在调试模式下运行代码,在递归函数的开头放置一个断点,然后跟踪代码,查看递归时的实际参数和返回值是什么.这样做几次,您将开始能够在不进行调试的情况下思考正在发生的事情。

(编辑:您可以使用的另一个技巧是写出列表推导长格式 - 使用 for 循环和 if/else 语句。它不那么紧凑,但通常更容易理解何时分配哪些值。)

【讨论】:

  • 在注意到 self.binaryTreePaths(root., val) 可以根据我自己的关联路径返回一个列表或字符串之后,我正在阅读这篇文章。然而,伟大的解释为这个问题提供了更多的启示。我想出了我在帖子的编辑部分下发布的可憎之处,但在阅读完这篇文章后,我将再次解决这个问题,因为我相信在这个帮助下我将能够想出一个更清洁的解决方案你的答案。此外,这很棒,因为现在我想我将来能够快速意识到是什么导致了这个问题。 :)
【解决方案2】:

对于这个问题,我们可以使用栈。这会被接受:

class Solution:
    def binaryTreePaths(self, root):
        if not root:
            return []

        paths = []
        stack = [(root, '')]
        while stack:
            node, path = stack.pop()
            if not node.left and not node.right:
                paths.append(f'{path}{node.val}')

            if node.right:
                stack.append((node.right, f'{path}{node.val}->'))

            if node.left:
                stack.append((node.left, f'{path}{node.val}->'))

        return paths

这里也是 LeetCode 的递归解决方案:

 class Solution:
    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        def construct_paths(root, path):
            if root:
                path += str(root.val)
                if not root.left and not root.right:  # if reach a leaf
                    paths.append(path)  # update paths  
                else:
                    path += '->'  # extend the current path
                    construct_paths(root.left, path)
                    construct_paths(root.right, path)

        paths = []
        construct_paths(root, '')
        return paths

参考文献

  • 有关其他详细信息,您可以查看Discussion Board。有很多公认的解决方案,有各种languages 和解释、高效的算法,以及渐近的time/space 复杂性分析1, 2

【讨论】:

  • 感谢您提供此解决方案。但是,我很抱歉没有在我的问题中说明我想使用递归方法而不是迭代方法,因为当我两个月前开始学习树遍历时,我开始只对所有事情使用迭代方法,现在我99% 的时间使用迭代方法来解决问题,并且总是回避使用递归解决方案,我希望通过专注于记住如何递归遍历树来解决这个问题。
  • 啊,我第一次看的时候错过了。感谢您分享这两个出色的解决方案!我已经掌握了一些新技巧,当我在大约 2-3 天内重做这个问题时,我将尝试并结合这些技巧。
猜你喜欢
  • 2020-08-14
  • 2013-02-14
  • 1970-01-01
  • 1970-01-01
  • 2013-11-05
  • 1970-01-01
  • 2019-07-01
  • 1970-01-01
  • 2015-09-02
相关资源
最近更新 更多