LeetCode Easy 437 路径之和III Python

    Disscusion Method

    算法:哈希表+DFS

    思路

        首先要想暴力解法是怎样进行的

            在暴力解法中,也就是下面我的那种解法,遍历每一个节点,在每一个节点的位置,还要向下遍历其他的每一个节点

        但是这样的话在遍历的过程中有很多遍历是重复的                         

                              10
                             /  \
                            5   -3
                           / \    \
                          3   2   11
                         / \   \
                        3  -2   1

            比如遍历到5的时候。会有5->3->3,3->3,10->5->3->3,其实就是一条路径,只不过每次的节点不一样罢了。

        但是用暴力解法遍历的话会重复遍历很多次,例如以10开头的时候遍历了10->5->3->3,后面又会以5开头遍历5->3->3

            所以首先要想的是,如何将一条路径拆成多条,因为根据题意,答案的路径不一定非要是从root开始的,所以在遍历

        过程中形成的path路径,能不能将他拆开?比如从10开始遍历,遍历路径10->5->3,能不能将其拆成10,5->3?

            答案当然是可以的,因为可以看做是从10出发了3层到达的这里,其实第一层10的时候就可以记录下来这个10,然后到

        10->5->3的时候,再"减去"前面单个节点10的情况就好了。

            所以这种解法就是基于这样的思想在遍历所有节点。并且联想TwoSum中的做法,用哈希表来存储要找的那个"加数"

            注意到本题中,要求的解的路径其实可以看做是一整条路径中的一部分,然后再根据上面讲到的将一条路径拆成多个

        部分组成。那么就可以设置一个哈希表,record,由record记录当前路径和的个数,{curr_sum:counter},

            由curr_sum来记录遍历到当前节点的路径和,如果一条目标路径在这条路径中,那么就可以按上述的拆分路径的方法求得

        当前子路径的前序路径和,即prefix_sum = curr_sum - target,然后在record中查询prefix_sum的个数。如果record

        中记录了这个prefix_sum,那么就表明当前路径中包含解,并且prefix_sum有几个,这样的路径就有几个

            如:10->5->3,target = 8,curr_sum - 8 = 10,而前面记录下来的record[10]=1,就说明有1条包含答案的路径,

        当然了,如果前面record[10]=n,那么就说明走到了10->5->3时,在这条路径上符合答案的路径就有n条,result += n

            所以在遍历的过程中应该record[curr_sum] += 1,记录下来curr_sum的个数,curr_sum在后面层数的递归中就相当于

        是prefix_sum了。

            所以根据以上思路dfs前序遍历二叉树,并且要注意的是当前节点的左右子树遍历完之后,要record[curr_sum] -= 1

            因为记录record[curr_sum] -= 1是为了记录当前路径和作为prefix的话有多少个,当前节点的子树遍历完之后,应该

        弹出当前节点的路径和,就像回溯的时候一样。比如还是10->5->3这里,记录了18后,遍历完这个③的节点,将18的个数减1,

        避免递归到⑩的右子树时,可能某个位置需要前面是18,但是误认为左子树的③这里记录的18是符合要求的,这样会将路径

        计算错。

            ❗️❗️❗️所以要明确,record[curr_sum]记录的是当前路径上有多少个子前缀路径的和是curr_sum,或者从子递归中看,应该叫

        record[prefix_sum]

    复杂度分析

        时间:ON,遍历一遍所有节点

        空间:ON,哈希表空间

def pathSum(self, root, sum):
    self.result = 0

    def dfs(root, record, curr_sum):
        if root == None:
            return
        curr_sum += root.val
        prefix_sum = curr_sum - sum
        if prefix_sum in record:
            self.result += record[prefix_sum]
        record.setdefault(curr_sum, 0)
        record[curr_sum] += 1
        dfs(root.left, record, curr_sum)
        dfs(root.right, record, curr_sum)
        record[curr_sum] -= 1

    dfs(root, {0: 1}, 0)
    return self.result



def pathSum1(self, root, sum):
    """
    My Brute Force Method
    算法:暴力
    思路:
        Do as they say
        遍历所有可能,dfs遍历每个节点,在每个节点位置向下深度遍历calculateSum()计算是否构成题解
        这里主要是会重复计算一些路径和,导致时间的浪费
    复杂度分析:
        时间:ON2
        空间:ON2
    """
    self.counter = 0
    def calculateSum(root,path_sum):
        if root == None :
            return
        path_sum += root.val
        if path_sum == sum:
            self.counter += 1
        calculateSum(root.left,path_sum)
        calculateSum(root.right,path_sum)
    def dfs(root):
        if root == None:
            return
        calculateSum(root,0)
        dfs(root.left)
        dfs(root.right)
    dfs(root)
    return self.counter

猜你喜欢

转载自blog.csdn.net/qq_28327765/article/details/85225484