zoukankan      html  css  js  c++  java
  • 剑指offer:二叉树中和为某一值的路径

    本来这只是一个普通的算法题,但是当初自己OJ上提交时,总是提交失败,而我自己认定程序逻辑没有任何问题。然后开始就在本机上调试,结果发现这是由于Python的对象机制而引发的。所以先把问题算法题贴出来,然后通过该问题,详述Python的对象机制!

    题目描述:

    输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

     

    这道题本身不难,书上、网上也有很多关于该问题的解释,这里我就直接贴上我的Python代码(该代码有一处很隐晦的bug)。

     1 # -*- coding:utf-8 -*-
     2 # class TreeNode:
     3 #     def __init__(self, x):
     4 #         self.val = x
     5 #         self.left = None
     6 #         self.right = None
     7 class Solution:
     8     # 返回二维列表,内部每个列表表示找到的路径
     9     def FindPath(self, root, expectNumber):
    10         # write code here
    11         if not root:
    12             return []
    13          
    14         ret = []   # 函数返回的二维列表
    15         path = []  # 遍历过程中经历的路径,假如符合条件,就加入到ret列表中
    16         self.Find(root, target, ret, path)
    17         return ret
    18          
    19          
    20     def Find(self, root, target, ret, path):
    21         if not root:
    22             return
    23              
    24         path.append(root.val)
    25         isLeaf = root.left is None and root.right is None
    26         if isLeaf and target == root.val:
    27             ret.append(path)    # 对于叶子节点,加上符合条件的path.
    28  
    29         if root.left:
    30             Find(root.left, target - root.val, ret, path)
    31         if root.right:
    32             Find(root.left, target - root.val, ret, path)
    33          
    34         path.pop()

    算法程序逻辑没有任何问题,却总是通不过OJ。一遍遍审查后,实在找不出哪里的错误,然后尝试调试。

     

     

    看到了吗?程序运行过程中,已经正确的把路径保存下来了。但是,最终程序返回的结果是包含两个[]的列表。

    如此,突然感觉豁然开朗了,于是,把第27行换成 ret.append(path[:])

    下面是改正后代码,成功通过OJ系统

    # -*- coding:utf-8 -*-
    class Solution:
        # 返回二维列表,内部每个列表表示找到的路径
        def FindPath(self, root, expectNumber):
            # write code here
            if not root:
                return []
     
            ret = []
            path = []
            self.Find(root, expectNumber, ret, path)
            # print ret
            # a = [];self.f(a);print a
            return ret
         
        def Find(self, root, target, ret, path):
            if not root:
                return
     
            path.append(root.val)
            isLeaf = (root.left is None and root.right is None)
            if isLeaf and target == root.val:
                ret.append(path[:])  # 这里这一步要千万注意啊,
                # 假如是:ret.append(path), 结果是错的。因为Python可变对象都是引用传递啊。
     
            #print "target:", target, "isLeaf:", isLeaf,
            #print "val:", root.val, "path:", path, "ret:", ret
            #print
     
            if root.left:
                self.Find(root.left, target - root.val, ret, path)
            if root.right:
                self.Find(root.right, target - root.val, ret, path)
     
            path.pop()

    至于为什么这小小的差别,会导致程序完全不同的运行行为,则涉及到Python的可变对象、不可变对象等机制。下一节,会对该问题进行详述!

  • 相关阅读:
    有关base64编码算法的相关操作
    不宜多吃的十种垃圾食品
    ~ 無 淚 的 天 使 ~
    Datagrid 中添加ComboBox 的两种方法(winform)
    刀兄写的IIS管理类(C#)
    17种常用正则表达式
    正则表达式经典 (转)
    C#中Pinvoke的使用
    C#中Pinvoke的使用2
    异步操作样本
  • 原文地址:https://www.cnblogs.com/bitpeng/p/4748148.html
Copyright © 2011-2022 走看看