20有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1: 示例 2: 示例 3: 示例 4: 示例 5:
输入: "()" 输入: "()[]{}" 输入: "(]" 输入: "([)]" 输入: "{[]}"
输出: true 输出: true 输出: false 输出: false 输出: true
class Solution:
def isValid(self, s: str) -> bool:
dic = {"{" :"}", "[" :"]", "(" :")",'?': '?'}
stack = ["?"]
for c in s:
if c in dic:
stack.append(c)
elif dic[stack.pop()] != c:
return False
return len(stack) == 1
# 栈先入后出特点恰好与本题括号排序特点一致
# 栈 stack 为空: 此时 stack.pop() 操作会报错;因此,我们采
# 用一个取巧方法,给 stack 赋初值 ??
二叉树
前序遍历:先访问根节点,再前序遍历左子树,再前序遍历右子树 (根左右)
中序遍历:先中序遍历左子树,再访问根节点,再中序遍历右子树 (左根右)
后序遍历:先后序遍历左子树,再后序遍历右子树,再访问根节点(左右根)
100. 相同的树
给定两个二叉树,编写一个函数来检验它们是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例 1:
输入: 1 1
/ \ / \
2 3 2 3
[1,2,3], [1,2,3]
输出: true
示例 2:
输入: 1 1
/ \
2 2
[1,2], [1,null,2]
输出: false
示例 3:
输入: 1 1
/ \ / \
2 1 1 2
[1,2,1], [1,1,2]
输出: false
class Solution:
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
if p == None and q == None:
return True
elif p == None or q == None:
return False
elif p.val != q.val:
return False
else:
return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
104. 二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最大深度 3 。
答案:
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root:
return 0
return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))
110. 平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回 true 。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1
/ \
2 2
/ \
3 3
/ \
4 4
返回 false 。
自顶而下的
思路是构造一个获取当前节点最大深度的方法 depth(root) ,通过比较此子树的左右子树的最大高度差abs(depth(root.left) - depth(root.right)),来判断此子树是否是二叉平衡树。若树的所有子树都平衡时,此树才平衡。
算法流程:
isBalanced(root) :判断树 root 是否平衡
特例处理: 若树根节点 root 为空,则直接返回 truetrue ;
返回值: 所有子树都需要满足平衡树性质,因此以下三者使用与逻辑 && 连接;
abs(self.depth(root.left) - self.depth(root.right)) <= 1 :判断 当前子树 是否是平衡树;
self.isBalanced(root.left) : 先序遍历递归,判断 当前子树的左子树 是否是平衡树;
self.isBalanced(root.right) : 先序遍历递归,判断 当前子树的右子树 是否是平衡树;
depth(root) : 计算树 root 的最大高度
终止条件: 当 root 为空,即越过叶子节点,则返回高度 00 ;
返回值: 返回左 / 右子树的最大高度加 11 。
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
def depth(root):
"""求当前节点的深度
Args: root: 节点
Returns:返回节点深度
"""
# 节点为空,返回高度 0
if not root:
return 0
# 否则返回左右子树最大高度值 +1
return max(depth(root.left), depth(root.right)) + 1
# 根节点为空,直接返回 True
if not root:
return True
# 否则递归判断
# 1. 当前子树是否平衡
# 2. 当前子树左子树是否平衡
# 3. 当前子树右子树是否平衡
return abs(depth(root.left)-depth(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)
124. 二叉树中的最大路径和
给定一个非空二叉树,返回其最大路径和。
本题中,路径被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。
示例 1:
输入:[1,2,3]
1
/ \
2 3
输出:6
示例 2:
输入:[-10,9,20,null,null,15,7]
-10
/ \
9 20
/ \
15 7
输出:42
class Solution:
def maxPathSum(self, root: TreeNode) -> int:
self.res = float("-inf")
# 我们先定义一个全局变量res=flaot("-inf")来存储全局的最大值,
# 也就是我们需要返回的值
def helper(root):
if not root:
return 0
# 左边最大值
left = helper(root.left)
# 右边最大值
right = helper(root.right)
# 和全局变量比较
self.res = max(left + right + root.val, self.res)
# >0 说明都能使路径变大
return max(0, max(left, right) + root.val)
helper(root)
return self.res
我们用题目的示例来描述一下这个算法过程:(理解如何递归很关键)
1. 从 dfs(-10) 开始,
1.1 dfs(9):
1.1.1 左孩子为空;贡献为 0
1.1.2 右孩子为空,贡献为 0
1.1.3 更新 res = max (-∞,(9 + 0 + 0)) = 9
1.1.4 返回 dfs(9) = 9 + max(左孩子贡献,右孩子贡献)) = 9
1.2 dfs(20)
1.2.1 dfs(15):
1.2.1.1 左孩子为空;贡献为0
1.2.1.2 右孩子为空,贡献为0
1.2.1.3 更新 res = max(9, 15 + 0 + 0) = 15
1.2.1.4 返回 dfs(15) = 15 + 0 = 15
1.2.2 dfs(7):
1.2.2.1 左孩子为空;贡献为 0
1.2.2.2 右孩子为空,贡献为 0
1.2.2.3 更新 res = max(15, 7 + 0 + 0) = 15
1.2.2.4 返回 dfs(7) = 7 + 0 = 7
1.2.3 更新 res = max (15, 20 + dfs(15) + dfs(7) ) = 42
1.2.4 返回dfs(20) = 20 + max(15, 7) = 35
1.3 更新 res = max(42, -10 + dfs(9) + dfs(20) ) = max(42, 34) = 42
1.4 返回 dfs(-10) = -10 + max(9, 35) = 25 (当然这一步就没啥用了,已经有最终res)
所以最大路径和 res = 42