查看: 2906| 回复: 16
跳转到指定楼层
上一主题 下一主题
收起左侧

[树/链表/图] LeetCode 236 树节点题, 疑问点在list的pop过程

全局:
1小米
236. Lowest Common Ancestor of a Binary Tree
找出两个节点的公共祖先
我遇到的问题是
首先我遍历搜索得到 path=[3,5]
然后我用深度复制result = copy.deepcopy(path)
接着我对path.pop()操作
但是这个时候我发现 path=[3].而result=[]. result的值太怪了,因为我已经深度复制了啊,应该是不变的,我不知道为什么,求各位大佬解答。谢谢

下面是我的代码:

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

import copy
class Solution:
    def lowestCommonAncestor(self, root, p, q):
        path = []
        node_p_path = []
        node_q_path = []
        finish = 0
        self.preorder(root, p, path, node_p_path, finish)
        path = []
        finish = 0
        self.preorder(root, q, path, node_q_path, finish)
        path_len = 0
        if len(node_p_path) < len(node_q_path):
            path_len = len(node_p_path)
        else:
            path_len = len(node_q_path)
        result = TreeNode(0)
        for i in range(path_len):
            if node_p_path[i] == node_q_path[i]:
                result = node_p_path[i]
        return result.val

    def preorder(self, node, search, path, result, finish):
        if not node or finish == 1:
            return
        path.append(node.val)
        if node.val == search.val:
            finish = 1
            result = copy.deepcopy(path)
        self.preorder(node.left, search, path, result, finish)

        self.preorder(node.right, search, path, result, finish)
        path.pop()


a=TreeNode(3)
b=TreeNode(5)
c=TreeNode(1)
d=TreeNode(6)
e=TreeNode(2)
f=TreeNode(0)
x=TreeNode(8)
y=TreeNode(7)
z=TreeNode(4)
a.left=b
a.right=c
b.left=d
b.right=e
c.left=f
c.right=x
e.left=y
e.right=z
x=Solution()
print(x.lowestCommonAncestor(a,b,f))



最佳答案

查看完整内容

我觉得return的方式更好,不过也可以尝试把result设为类的attribute(self.result),类似全局变量的感觉

上一篇:我第一次的leetcode contribution的感受
下一篇:刷题进阶小tip
全局:
李冬冬 发表于 2019/06/03 14:48:57


有点明白了,但是该如何去改这个问题?在递归自程序里return这个值?万分感谢

我觉得return的方式更好,不过也可以尝试把result设为类的attribute(self.result),类似全局变量的感觉
回复

使用道具 举报

🔗
Jarvet 2019-6-3 14:17:00 | 只看该作者
全局:
半夜睡不着看到悬赏精神了答一下。。。大概看了看,如有不对还请指正
先说结论,不是deep copy的问题,是参数传递
python 是传引用的,楼主最开始传入result参数,假设引用是A,然后deepcopy,递归子程序中的result引用被改成了B,也就导致了最初传入的引用A的数据其实并没有改变,而最后楼主输出的正式这个A的result,所以依然是空的,而至于B的内容,已经随着层层递归的结束而被销毁了
楼主可以分别在对应位置print(id(result))来查看,应该会好理解些
回复

使用道具 举报

🔗
 楼主| Tokyo职人 2019-6-3 14:48:57 | 只看该作者
全局:
Jarvet 发表于 2019-6-3 14:17
半夜睡不着看到悬赏精神了答一下。。。大概看了看,如有不对还请指正
先说结论,不是deep copy的问题,是 ...

有点明白了,但是该如何去改这个问题?在递归自程序里return这个值?万分感谢
回复

使用道具 举报

🔗
 楼主| Tokyo职人 2019-6-4 13:24:06 | 只看该作者
全局:
Jarvet 发表于 2019-6-3 11:05
我觉得return的方式更好,不过也可以尝试把result设为类的attribute(self.result),类似全局变量的感觉

如下是我改的,还是不行,求帮忙改一下(捂脸),感激
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

import copy
class Solution:
    resultpath = []
    def lowestCommonAncestor(self, root, p, q):
        path = []
        node_p_path = []
        node_q_path = []
        finish = 0
        self.preorder(root, p, path, node_p_path, finish)
        path = []
        finish = 0
        self.preorder(root, q, path, node_q_path, finish)
        path_len = 0
        if len(node_p_path) < len(node_q_path):
            path_len = len(node_p_path)
        else:
            path_len = len(node_q_path)
        result = TreeNode(0)
        for i in range(path_len):
            if node_p_path[i] == node_q_path[i]:
                result = node_p_path[i]
        return result.val

    def preorder(self, node, search, path, resultpath, finish):
        if not node or finish == 1:
            return
        path.append(node.val)
        if node.val == search.val:
            finish = 1
            self.resultpath = copy.deepcopy(path)
        self.preorder(node.left, search, path, self.resultpath, finish)
        self.preorder(node.right, search, path, self.resultpath, finish)
        path.pop()
回复

使用道具 举报

🔗
 楼主| Tokyo职人 2019-6-4 13:25:36 | 只看该作者
全局:
李冬冬 发表于 2019-6-3 14:48
有点明白了,但是该如何去改这个问题?在递归自程序里return这个值?万分感谢

return我改成了如下,还是不行。。。求解答
    def preorder(self, node, search, path, resultpath, finish):
        if not node or finish == 1:
            return
        path.append(node.val)
        if node.val == search.val:
            finish = 1
            resultpath = copy.deepcopy(path)
            return resultpath
        self.preorder(node.left, search, path, resultpath, finish)
        self.preorder(node.right, search, path, resultpath, finish)
        path.pop()
回复

使用道具 举报

全局:
李冬冬 发表于 2019/06/04 13:25:36


return我改成了如下,还是不行。。。求解答
    def preorder(self, node, search, path, resultpath, finish):
        ...

你的第一个return没返回东西

补充内容 (2019-6-4 14:23):
其他的不太好描述…其实可以单靠return不用path和resultpath的,左右preorder的结果如果都存在,那就一定是当前节点,如果只存在一个,那就在存在的这一侧,大概是这样的思路,感觉path好像有点点多余…楼主思路是?

补充内容 (2019-6-4 14:28):
字数不够了,楼主思路是两边都搜到头然后再找对么,那样的话现在这样好像逻辑有些混乱了。。第一preorder的结果并没有return出来,第二分别搜时间上会很慢…
回复

使用道具 举报

🔗
 楼主| Tokyo职人 2019-6-4 14:24:33 | 只看该作者
全局:
Jarvet 发表于 2019-6-4 14:11
你的第一个return没返回东西

补充内容 (2019-6-4 14:23):

还是没用啊,求教   
def preorder(self, node, search, path, resultpath, finish):
        if not node or finish == 1:
            return resultpath
        path.append(node.val)
        if node.val == search.val:
            finish = 1
            resultpath = copy.deepcopy(path)
        self.preorder(node.left, search, path, resultpath, finish)
        self.preorder(node.right, search, path, resultpath, finish)
        path.pop()
回复

使用道具 举报

🔗
 楼主| Tokyo职人 2019-6-4 14:35:39 | 只看该作者
全局:
Jarvet 发表于 2019-6-4 14:11
你的第一个return没返回东西

补充内容 (2019-6-4 14:23):

我发现用append可以避免这一点。。。传参我看了,但是没看懂。。   
def preorder(self, node, search, path, resultpath, finish):
        if not node or finish == 1:
            return
        path.append(node.val)
        if node.val == search.val:
            finish = 1
            resultpath.append(copy.deepcopy(path))
        self.preorder(node.left, search, path, resultpath, finish)
        self.preorder(node.right, search, path, resultpath, finish)
        path.pop()
回复

使用道具 举报

🔗
Jarvet 2019-6-4 14:56:18 | 只看该作者
全局:
楼主你最后for循环i给丢了。。。
试着按楼主思路改了下。。。感觉改动还蛮大的,细节问题也比较多,直接贴代码好了,有些地方注释掉了看起来会比较乱……
  1.     def lowestCommonAncestor(self, root, p, q):
  2.         path = []
  3.         # node_p_path = []
  4.         # node_q_path = []
  5.         # finish = 0
  6.         node_p_path = self.preorder(root, p, path)
  7.         path = []
  8.         # finish = 0
  9.         node_q_path = self.preorder(root, q, path)
  10.         # path_len = 0
  11.         if len(node_p_path) < len(node_q_path):
  12.             path_len = len(node_p_path)
  13.         else:
  14.             path_len = len(node_q_path)
  15.         # result = TreeNode(0)
  16.         for i in range(path_len):
  17.             # if node_p_path == node_q_path:
  18.             if node_p_path[i] == node_q_path[i]:
  19.                 result = node_p_path[i]
  20.         # return result.val
  21.         return result

  22.     def preorder(self, node, search, path):
  23.         # if not node or finish == 1:
  24.         #     return
  25.         if not node:
  26.             return []
  27.         # path.append(node.val)
  28.         path.append(node)
  29.         if node.val == search.val:
  30.             # finish = 1
  31.             return path
  32.             # resultpath = copy.deepcopy(path)
  33.             # return resultpath
  34.         left = self.preorder(node.left, search, path)
  35.         if left:
  36.             return left
  37.         # path.pop()
  38.         right = self.preorder(node.right, search, path)
  39.         if right:
  40.             return right
  41.         path.pop()
复制代码

评分

参与人数 2大米 +4 收起 理由
14417335 + 3
Tokyo职人 + 1 感谢!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表