python - 如何优化解决方案以避免超出内存限制错误或什么可能让我出错?

标签 python algorithm optimization depth-first-search

我遇到了以下问题。

You are given the root of a binary tree with n nodes. 
Each node is uniquely assigned a value from 1 to n. 
You are also given an integer startValue representing 
the value of the start node s, 
and a different integer destValue representing 
the value of the destination node t.

Find the shortest path starting from node s and ending at node t. 
Generate step-by-step directions of such path as a string consisting of only the 
uppercase letters 'L', 'R', and 'U'. Each letter indicates a specific direction:

'L' means to go from a node to its left child node.
'R' means to go from a node to its right child node.
'U' means to go from a node to its parent node.
Return the step-by-step directions of the shortest path from node s to node t

示例 1: enter image description here

Input: root = [5,1,2,3,null,6,4], startValue = 3, destValue = 6
Output: "UURL"
Explanation: The shortest path is: 3 → 1 → 5 → 2 → 6.

示例 2:

enter image description here

Input: root = [2,1], startValue = 2, destValue = 1
Output: "L"
Explanation: The shortest path is: 2 → 1.

我通过找到最不常见的祖先然后进行深度优先搜索来找到元素来创建解决方案,就像这样:-

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def getDirections(self, root, startValue, destValue):
        """
        :type root: Optional[TreeNode]
        :type startValue: int
        :type destValue: int
        :rtype: str
        """

        def lca(root):
            if root == None or root.val == startValue or root.val == destValue:
                return root
        
            left = lca(root.left)
            right = lca(root.right)
        
            if left and right:
                return root
        
            return left or right
    
        def dfs(root, value, path):
            if root == None:
                return ""
        
            if root.val == value:
                return path
        
            return dfs(root.left, value, path + "L") + dfs(root.right, value, path + "R")
        
        
        root = lca(root)
        return "U"*len(dfs(root, startValue, "")) + dfs(root, destValue, "")
    

该解决方案运行良好,但是对于非常大的输入,它会抛出“超出内存限制”错误,谁能告诉我如何优化该解决方案,或者我可能会做些什么才能让我参与其中?

最佳答案

超出内存限制的原因是 dfs 函数的参数。您的“路径”变量是一个字符串,它可以和树的高度一样大(如果不平衡,它可以是整棵树的大小)。

通常这不会有问题,但 path + "L" 会为函数的每次递归调用创建一个新字符串。除了非常慢之外,这还意味着您的内存使用量为 O(n^2),其中 n 是树中的节点数。

例如,如果您的最终路径是 "L"* 1000,您的 dfs 调用堆栈将如下所示:

Depth 0: dfs(root, path = "")
Depth 1: dfs(root.left, path = "L")
Depth 2: dfs(root.left.left, path = "LL")
...
Depth 999:  path = "L"*999
Depth 1000:  path = "L"*1000

尽管所有这些变量都被称为 path,但它们都是完全不同的字符串,总内存使用量为 ~(1000*1000)/2 = 500,000 个字符一度。有 100 万个节点,这是 5000 亿个字符。

现在,这并不仅仅因为字符串是不可变的;事实上,即使您使用的是列表(可变的),您仍然会遇到这个问题,因为 path + ["L"] 仍然会被迫创建 path 的副本。

要解决这个问题,您需要在 dfs 函数之外为 path 存储一个变量,并且只从递归的 dfs 附加到它 功能。这将确保您只使用 O(n) 空间。

def dfs(root, value, path):
    if root is None:
        return False

    if root.val == value:
        return True

    if dfs(root.left, value, path):
        path.append("L")
        return True
    elif dfs(root.right, value, path):
        path.append("R")
        return True
    return False

root = lca(root)
start_to_root = []
dfs(root, startValue, start_to_root)

dest_to_root = []
dfs(root, destValue, dest_to_root)

return "U" * len(start_to_root) + ''.join(reversed(dest_to_root))

关于python - 如何优化解决方案以避免超出内存限制错误或什么可能让我出错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71343736/

相关文章:

algorithm - Codeforces 第 255 轮 "Modifying matrix"解决方案(Div-1 B)?

java - 尝试用Java实现一种旅行者算法

python - 我如何使用 Python Pandas "merge/add"2 个具有相同列和行的混淆矩阵数据帧?

python - Python的语法是LL(1)吗?

从两个集合中匹配对的算法

Java - 自定义单链表,删除所有出现的具有特定值的元素

python - Tensorflow 中的 Dice/Jaccard 系数优化

c++ - 可以为了速度牺牲常量正确性吗?

python - 使用python为直方图中的特定条形着色

python - 如何将python语法错误重定向到MFC或其他GUI框架中的文本框?