前言
二叉树(3)
以后这个栏目的博客会精简一些,只记录必要的核心代码和关键思考
LeetCode 257. 二叉树的所有路径
主要思想
这是第一次使用回溯算法,重点要理解几个问题:
- 为什么要使用前序遍历
因为是路径搜索的顺序必然是父节点指向子节点 - 本题递归的终止条件是什么?终止时的操作是什么?
终止条件是找到叶子节点,此时意味着找到一条完整的路径,会将此路径存入result中,并向上一个节点回溯。 - 为什么递归和回溯必然在一起
递归是从大到小(本题采用前序遍历,故具体表现为从上到下)的套娃,而回溯则是在这一套娃过程中加入了a.频繁变动的“数组”和b.持续累积的结果池,二者都是全局变量,分别对应本题的path和result。
LeetCode 101. 对称二叉树
主要思想
利用后序遍历,分别对左右子树进行“左右中”遍历和“右左中”遍历方式。
Debug过程
处理递归“弹出选项”时候要注意考虑左右节点为空的情况(最终的递归题解采用了4种方式进行讨论),因为当其中一个节点为空时,二者也不相等,但是无法分别取val值。
LeetCode 404.左叶子之和
主要思想
这一题比较简单,重点要体会面向对象在设置对象内部“全局变量”上的便捷。
正确的:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
if root == None: return 0
if not root.left and not root.right: return 0
self.result = 0
self.traverse(root)
return self.result
def traverse(self, cur):
if not cur.left and not cur.right:
self.result += (self.mark * cur.val)
if cur.left:
self.mark = 1
self.traverse(cur.left)
if cur.right:
self.mark = 0
self.traverse(cur.right)
错误的:
使用的是result而非self.result,在多次递归后创建了多个result的形参而不是result本题
不同的是,如果使用list.append()等方法传递到就是本题,例如本博客上一题。
LeetCode 222.完全二叉树的节点个数
主要思想
利用好完全二叉树的性质,缩短计数时间即可。