代码随想录算法训练营第17天|二叉树part4|110. 平衡二叉树、 257. 二叉树的所有路径 (优先掌握递归)、404.左叶子之和
110. 平衡二叉树
定义:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。(注意是高度差,不是深度差)
自己做
思想:
遍历二叉树的每个结点,求其左右孩子的高度差,如果每个结点的高度差都小于等于1范围内,那就是平衡二叉树
代码:
python
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def isBalanced(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
# 遍历二叉树的每个结点
# 前序遍历:中左右
if root == None:
return True
leftDepth = self.getDepth(root.left)
rightDepth = self.getDepth(root.right)
if abs(leftDepth - rightDepth) <= 1:
return self.isBalanced(root.left) and self.isBalanced(root.right)
else:
return False
def getDepth(self, root):
if root == None:
return 0
leftDepth = self.getDepth(root.left)
rightDepth = self.getDepth(root.right)
return 1 + max(leftDepth, rightDepth)
代码随想录
思想:
二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。
leetcode中强调的深度和高度很明显是按照节点来计算的,如图:
因为求深度可以从上到下去查 所以需要前序遍历(中左右)
而高度只能从下到上去查,所以只能后序遍历(左右中)
注意是高度不是深度!!!
代码:
python
递归
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def isBalanced(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
# 遍历二叉树的每个结点
# 前序遍历:中左右
if root == None:
return True
leftHeight = self.getHeight(root.left)
rightHeight = self.getHeight(root.right)
if abs(leftHeight - rightHeight) <= 1:
return self.isBalanced(root.left) and self.isBalanced(root.right)
else:
return False
# 后序遍历(左右中)自叶子结点到指定结点求 高度
def getHeight(self, root):
if root == None:
return 0
leftHeight = self.getHeight(root.left)
rightHeight = self.getHeight(root.right)
return 1 + max(leftHeight, rightHeight)
迭代
257. 二叉树的所有路径 (优先掌握递归)
自己做
思路:
首先,记录从根结点到叶子结点的路径,需要遍历->前序遍历
其次,记录路径->双端队列
再次,打印路径->打印函数
最后, 记录路径的双端队列如何跟随递归的路线进行出队和入队. 回溯
代码:
python
from collections import deque
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def binaryTreePaths(self, root):
"""
:type root: TreeNode
:rtype: List[str]
"""
# 前序遍历(中左右)所有结点,并把经过的结点保存在双端队列中
# return 时,相应的结点也出队
# 遇到叶子结点就打印路径,append到结果列表中
dequeue = deque()
result = []
self.preOrder(root, dequeue, result)
return result
def preOrder(self, root, dequeue, result):
if root == None:
return None
dequeue.append(root)
if root.left == None and root.right == None:
result.append(self.printPath(dequeue))
dequeue.pop()
return result
self.preOrder(root.left, dequeue, result)
self.preOrder(root.right, dequeue, result)
dequeue.pop()
def printPath(self, dequeue):
path = ""
path += str(dequeue[0].val)
for index in range(1, len(dequeue)):
path += '->'
path += str(dequeue[index].val)
return path
代码随想录
思路
在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,需要回溯来回退一个路径再进入另一个路径。
前序遍历以及回溯的过程如图:
代码
python
递归 + 回溯
# Definition for a binary tree node.
class Solution:
def traversal(self, cur, path, result):
path.append(cur.val) # 中
if not cur.left and not cur.right: # 到达叶子节点
sPath = '->'.join(map(str, path))
result.append(sPath)
return
if cur.left: # 左
self.traversal(cur.left, path, result)
path.pop() # 回溯
if cur.right: # 右
self.traversal(cur.right, path, result)
path.pop() # 回溯
def binaryTreePaths(self, root):
result = []
path = []
if not root:
return result
self.traversal(root, path, result)
return result
迭代
404.左叶子之和
自己做
就是按照左叶子之和的定义来:
-
叶子结点:左孩子为空,右孩子为空
-
是左孩子:判断是否为左孩子,需要知道其父亲结点,所以需要前驱节点
代码:
python
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def sumOfLeftLeaves(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
if root and root.left and not root.left.left and not root.left.right:
return root.left.val + self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)
else:
return self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)
代码随想录
左叶子的明确定义:
节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点
如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子,判断代码如下:
if (node->left != NULL && node->left->left == NULL && node->left->right == NULL) {
左叶子节点处理逻辑
}
代码:
python
递归