Leetcode 513 查找树左下角的值
题目:
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
示例 1:
输入: root = [2,1,3]
输出: 1
示例 2:
输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7
提示:
- 二叉树的节点个数的范围是 [1, 1 0 4 10^4 104]
- - 2 31 2^{31} 231 <= Node.val <= 2 31 2^{31} 231 - 1
算法思想:
误区:有可能会认为最左边的值来自于左子树,这样认为是错误的。也可能来源于右子树,只不过此时的右子树是最后一层从左到右的第一个节点。
- 递归法:
递归参数:传入根节点,子函数传入当前节点的深度(最后一层的节点肯定是最深层的节点,所以要传入当前节点的深度)
递归结束条件:(注意:当前寻找树左下角的值一定是遍历完整棵树,在遍历期间满足条件反复更新当前最左边的变量即可)如果当前节点是叶子结点,并且当前节点的深度大于之前遍历的所有节点的最大深度,更新结果于最大深度的值。
一次递归逻辑:如果左子树不空,深度加1,同时左递归,递归结束返回上一层深度减一(回溯)。如果右子树不空,深度加1,递归结束返回上一层深度减一(回溯) - 迭代法:利用类似层次遍历法,注意遍历每一层的第一个节点就是当前二叉树的最左侧节点。
代码实现:
- 递归法:
# 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 findBottomLeftValue(self, root) -> int:
if root is None:
return 0 # 题目中给出的是最少一个节点
self.result = None
self.max_depth = float('-inf')
self.traversal(root, 0)
return self.result
def travelsal(self, root, depth):
# root 当前遍历的节点
# 当前节点的深度 二叉树的根节点深度位0
if root.left is None and root.right is None:
if depth > self.max_depth:
self.result = root.val
self.max_depth = depth
if root.left:
depth = depth + 1
self.travelsal(root.left)
depth = depth - 1
if root.right:
depth = depth + 1
self.travelsal(root.right)
depth = depth - 1
- 迭代法:
# 定义TreeNode
class TreeNode:
def __init__(self, val=0, left=None, right=None) -> None:
self.val = val
self.left = left
self.right = right
import collections
class Solution:
def findBottomLeftValue(self, root):
if root is None:
return 0
result = 0
queue = collections.deque([root])
while queue:
for i in range(len(queue)):
cur = queue.popleft()
if i == 0:
result = cur.val
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
return result
Leetcode 112 路径总和
题目:
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
示例 2:
输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。
示例 3:
输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。
提示:
- 树中节点的数目在范围 [0, 5000] 内
- -1000 <= Node.val <= 1000
- -1000 <= targetSum <= 1000
算法思想:
- 递归法:
递归参数:传入根节点,targetNum
递归结束条件:(注意:和上一道题一样,并不涉及“中”节点的逻辑处理,因此前中后序遍历都可以)当前节点的左右孩子节点都是空节点的时候,即当前节点是叶子结点且targetNum减到0 或者路径上的节点值的和为targetNum的时候返回True,否则当前节点是叶子结点且路径和不等于targetNum的时候返回False。
一次递归逻辑:递归遍历左子树,同时剪枝操作(即如果当前节点接收到子节点的返回值为True,即返回True),否则继续遍历;递归遍历右子树,同时剪枝操作(类似左子树) - 迭代法:迭代法定义两个栈,第一个栈存当前遍历的节点;第二个栈存遍历到当前节点的val 之和。类似于先序遍历。
代码实现:
- 递归法:
# 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 traversal(self, root: TreeNode, count: int) -> bool:
if root.left is None and root.right is None and count == 0:
return True
if root.left is None and root.right is None and count != 0:
return False
if root.left:
count -= root.left.val
# 相当于剪枝的操作
if self.traversal(root.left, count):
return True
count += root.left.val
if root.right:
count -= root.right.val
# 相当于剪枝操作
if self.traversal(root.right, count):
return True
count += root.right.val
return False
def hasPathSum(self, root, targetSum) -> bool:
if root is None:
return False
return self.traversal(root, targetSum-root.val)
- 迭代法
# 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 hasPathSum(self, root, targetSum) -> bool:
if root is None:
return False
st = [root]
sum_st = [root.val]
while st:
cur = st.pop()
num = sum_st.pop()
if cur.left is None and cur.right is None and num == targetSum:
return True
if cur.left:
st.append(cur.left)
sum_st.append(num+cur.left.val)
if cur.right:
st.append(cur.right)
sum_st.append(num+cur.right.val)
return False
[Leetcode 106 从中序与后序遍历序列构造二叉树
](https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/)
题目:
给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]
示例 2:
输入:inorder = [-1], postorder = [-1]
输出:[-1]
提示:
- 1 <= inorder.length <= 3000
- postorder.length == inorder.length
- -3000 <= inorder[i], postorder[i] <= 3000
- inorder 和 postorder 都由 不同 的值组成
- postorder 中每一个值都在 inorder 中
- inorder 保证是树的中序遍历
- postorder 保证是树的后序遍历
算法思想:
本题利用递归思想。主要分成六个步骤:
第一,判断后序遍历是否为空(题目中给出postorder和inorder符合后序和中序的条件,因此不用过多的条件判断),如果为空,直接返回None,返回值哪里接?接下来递归中接。
第二,后序遍历的最后一个节点就是当前二叉树的根节点
第三,从中序遍历中找到根节点的位置
第四,从中序遍历中切出左右子序列
第五,从后序遍历中切出左右子序列
第六,递归遍历左右子序列
第七,返回二叉树的根节点
代码实现:
# 定义二叉树
class TreeNode:
def __init__(self, val=0, left=None, right=None) -> None:
self.val = val
self.left = left
self.right = right
class Solution:
def buildTree(self, inorder, postorder):
# 第一步
if len(postorder) == 0:
return None
# 第二步
root_val = postorder[-1]
root = TreeNode(root_val)
# 第三步,寻找切割点
separator_index = inorder.index(root_val)
# 第四步,切割中序数组
inorder_left = inorder[:separator_index]
inorder_right = inorder[separator_index+1:]
# 第五步,切割后序数组
post_left = postorder[:len(inorder_left)]
post_right = postorder[len(inorder_left):-1]
# 第六步,递归
root.left = self.buildTree(inorder_left, post_left)
root.right = self.buildTree(inorder_right, post_right)
# 第七步,返回root
return root
import unittest
class TestSolution(unittest.TestCase):
def test_buildTree(self):
solution = Solution()
# Test case 1
inorder1 = [9, 3, 15, 20, 7]
postorder1 = [9, 15, 7, 20, 3]
result1 = solution.buildTree(inorder1, postorder1)
self.assertEqual(result1.val, 3)
self.assertEqual(result1.left.val, 9)
self.assertEqual(result1.right.val, 20)
self.assertEqual(result1.right.left.val, 15)
self.assertEqual(result1.right.right.val, 7)
# Test case 2
inorder2 = [2, 1]
postorder2 = [2, 1]
result2 = solution.buildTree(inorder2, postorder2)
self.assertEqual(result2.val, 1)
self.assertEqual(result2.left.val, 2)
# Test case 3
inorder3 = [1, 2]
postorder3 = [2, 1]
result3 = solution.buildTree(inorder3, postorder3)
self.assertEqual(result3.val, 1)
self.assertEqual(result3.right.val, 2)
if __name__ == '__main__':
unittest.main()