LeetCode #100 #112 #113 #437 #129 #114 2018-08-10

Part 4 – 杂鱼

100. Same Tree

https://leetcode.com/problems/same-tree/description/

DFS的一种。注意if语句排他性的巧妙应用。
代码如下:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isSameTree(self, p, q):
        """
        :type p: TreeNode
        :type q: TreeNode
        :rtype: bool
        """
        if not p and not q:
            return True
        if not p or not q:
            return False
        if p.val != q.val:
            return False
        return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)

112. Path Sum

https://leetcode.com/problems/path-sum/description/

这道题是树操作的题目,判断是否从根到叶子的路径和跟给定sum相同的。还是用常规的递归方法来做,递归条件是看左子树或者右子树有没有满足条件的路径,也就是子树路径和等于当前sum减去当前节点的值。结束条件是如果当前节点是空的,则返回false,如果是叶子,那么如果剩余的sum等于当前叶子的值,则找到满足条件的路径,返回true。算法的复杂度是树的遍历,时间复杂度是O(n),空间复杂度是O(logn)
代码如下:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if not root:
            return False
        if root.val == sum and not root.left and not root.right:
            return True
        return self.hasPathSum(root.left, sum-root.val) or self.hasPathSum(root.right, sum-root.val)

树的题目基本都是用递归来解决,主要考虑两个问题:
1)如何把问题分治成子问题给左子树和右子树。这里就是看看左子树和右子树有没有存在和是sum减去当前结点值得路径,只要有一个存在,那么当前结点就存在路径。
2)考虑结束条件是什么。这里的结束条件一个是如果当前节点为空,则返回false。另一个如果是叶子,那么如果剩余的sum等于当前叶子的值,则找到满足条件的路径,返回true。

113. Path Sum II

https://leetcode.com/problems/path-sum-ii/description/

思路和Path Sum是完全一样的,只是需要输出所有路径,所以需要数据结构来维护路径,添加两个参数,一个用来维护走到当前结点的路径,一个用来保存满足条件的所有路径,思路上递归条件和结束条件是完全一致的,空间上这里会依赖于结果的数量了。时间复杂度仍然只是一次遍历O(n),而空间复杂度则取决于满足条件的路径和的数量(假设是k条),则空间是O(klogn)
注意,非空判断不是在进入递归前,就是在刚进入递归时,总之要有一个对空的判断,不然会有空指针异常。
代码如下:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def pathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: List[List[int]]
        """
        result = []
        self.helper(root, sum, [], result)
        return result
    
    def helper(self, root, sum, path, result):
        if not root:
            return
        if root.val == sum and not root.left and not root.right:
            result.append(list(path+[root.val]))
            return
        self.helper(root.left, sum-root.val, path+[root.val], result)
        self.helper(root.right, sum-root.val, path+[root.val], result)

437. Path Sum III

https://leetcode.com/problems/path-sum-iii/description/

Two Sum Method: Optimized Solution

A more efficient implementation uses the Two Sum idea. It uses a hash table (extra memory of order N). With more space, it gives us an O(N) complexity.
As we traverse down the tree, at an arbitrary node N, we store the sum until this node N (sum_so_far (prefix) + N.val). in hash-table. Note this sum is the sum from root to N.
Now at a grand-child of N, say G, we can compute the sum from the root until G since we have the prefix_sum until this grandchild available.We pass in our recursive routine.
How do we know if we have a path of target sum which ends at this grand-child G? Say there are multiple such paths that end at G and say they start at A, B, C where A,B,C are predecessors of G. Then sum(root->G) - sum(root->A) = target. Similarly sum(root->G)-sum(root>B) = target. Therefore we can compute the complement at G as sum_so_far+G.val-target and look up the hash-table for the number of paths which had this sum.
Now after we are done with a node and all its grandchildren, we remove it from the hash-table. This makes sure that the number of complement paths returned always correspond to paths that ended at a predecessor node.
代码如下:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def pathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: int
        """
        self.result = 0
        self.helper(root, sum, 0, {0:1})
        return self.result
    
    def helper(self, root, target, pre_sum, sums):
        if not root:
            return
        cur_sum = pre_sum + root.val
        if cur_sum - target in sums:
            self.result += sums[cur_sum - target]
        sums.setdefault(cur_sum, 0)
        sums[cur_sum] += 1
        self.helper(root.left, target, cur_sum, sums)
        self.helper(root.right, target, cur_sum, sums)
        sums[cur_sum] -= 1

129. Sum Root to Leaf Numbers

https://leetcode.com/problems/sum-root-to-leaf-numbers/description/

递归到的结点分2种情况:结点为叶子结点,将总和加入到最终结果中去;结点非叶子结点,继续递归其子结点即可。
算法的本质是一次先序遍历,所以时间复杂度是O(n),空间是栈大小,即O(logn)
代码如下:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def sumNumbers(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.result = 0
        self.helper(root, 0)
        return self.result
    
    def helper(self, root, num):
        if not root:
            return
        value = num * 10 + root.val
        if not root.left and not root.right:
            self.result += value
            return
        self.helper(root.left, value)
        self.helper(root.right, value)

114. Flatten Binary Tree to Linked List

https://leetcode.com/problems/flatten-binary-tree-to-linked-list/description/

相当于一个反着的先序遍历。用pre保存上一个访问的结点,然后对当前结点进行处理。
代码如下:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def flatten(self, root):
        """
        :type root: TreeNode
        :rtype: void Do not return anything, modify root in-place instead.
        """
        self.pre = None
        self.helper(root)
        
    def helper(self, root):
        if not root:
            return None
        self.helper(root.right)
        self.helper(root.left)
        root.right = self.pre
        root.left = None
        self.pre = root
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,449评论 0 10
  • 我劝你做人要潇洒 敬往事一杯酒 再爱也不回头 可是啊 实际就算我醉到黄昏独自愁 如果你伸出手 我还是会跟你走 我还...
    琉璃珀阅读 134评论 0 1
  • 最近又重看了一遍小时候非常喜欢的电视剧《天外飞仙》,发觉这么多年过去了还是那么喜欢,那么的触动人心。不管是故事情节...
    两朵隔墙花阅读 338评论 1 2
  • “当你把时间拉长到年的时候,很多行为都会原形毕露。不管你装了多大的逼,这些最后都会在时间的作用下,一一拆散。所以久...
    张晃晃阅读 981评论 1 2