🌳 表示当前进度
🌺 表示已完成
一棵树要么是空树,要么有两个指针,每个指针指向一棵树。树是一种递归结构,很多树的问题可以使用递归来处理。
104. Maximum Depth of Binary Tree (Easy)
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if root == None:
return 0
else:
return max(1 + self.maxDepth(root.left), 1 + self.maxDepth(root.right))110. Balanced Binary Tree (Easy)
3
/ \
9 20
/ \
15 7平衡树左右子树高度差都小于等于 1
class Solution(object):
def isBalanced(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if root==None:
return True
self.balance = True
self.subBalance(root)
return self.balance
def subBalance(self,root):
if root==None:
return 0
left = self.subBalance(root.left)
right = self.subBalance(root.right)
if abs(left-right)>1:
self.balance = False
return 1 + max(left,right)543. Diameter of Binary Tree (Easy)
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过根结点。
示例 :
给定二叉树
1
/ \
2 3
/ \
4 5
返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。
注意:两结点之间的路径长度是以它们之间边的数目表示。class Solution(object):
def diameterOfBinaryTree(self, root):
if root==None:
return 0
self.diameter = 0
self.helper(root)
return self.diameter - 1 # 减1是因为最长路径的”顶点“被两边的”半径“包含,计算了两次
def helper(self, root):
if root == None:
return 0
left = self.helper(root.left)
right = self.helper(root.right)
d = left + 1 + right # 以当前root为顶点的最长路径
self.diameter = max(d, self.diameter)
return max(1+left, 1+right) # 当前root对应的最长“半径”226. Invert Binary Tree (Easy)
class Solution(object):
def invertTree(self, root):
if root==None:
return
root.left, root.right = root.right, root.left
self.invertTree(root.left)
self.invertTree(root.right)
return root617. Merge Two Binary Trees (Easy)
Input:
Tree 1 Tree 2
1 2
/ \ / \
3 2 1 3
/ \ \
5 4 7
Output:
3
/ \
4 5
/ \ \
5 4 7class Solution:
def mergeTrees(self, t1, t2):
if t1==None and t2==None:
return None
if t1==None or t2==None:
return t1 or t2
newt = TreeNode(t1.val + t2.val)
newt.left = self.mergeTrees(t1.left, t2.left)
newt.right = self.mergeTrees(t1.right, t2.right)
return newtLeetcdoe : 112. Path Sum (Easy)
Given the below binary tree and sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.路径和定义为从 root 到 leaf 的所有节点的和。
class Solution:
def hasPathSum(self, root, target) :
if root==None:
return False
if root.left==None and root.right==None and root.val==target:
return True
return self.hasPathSum(root.left,target-root.val) or self.hasPathSum(root.right,target-root.val)root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
10
/ \
5 -3
/ \ \
3 2 11
/ \ \
3 -2 1
Return 3. The paths that sum to 8 are:
1. 5 -> 3
2. 5 -> 2 -> 1
3. -3 -> 11路径不一定以 root 开头,也不一定以 leaf 结尾,但是必须连续。
class Solution(object):
def pathSum(self, root, target):
if root==None:
return 0
return self.helper(root,target) + self.pathSum(root.left,target) + self.pathSum(root.right, target)
def helper(self, root, target):
if root==None:
return 0
cur = 0
if root.val==target:
cur = 1
return cur + self.helper(root.left,target-root.val)+self.helper(root.right, target-root.val)572. Subtree of Another Tree (Easy)
Given tree s:
3
/ \
4 5
/ \
1 2
Given tree t:
4
/ \
1 2
Return true, because t has the same structure and node values with a subtree of s.
Given tree s:
3
/ \
4 5
/ \
1 2
/
0
Given tree t:
4
/ \
1 2
Return false.class Solution:
def isSubtree(self, t1: TreeNode, t2: TreeNode) -> bool:
if t1==None or t2==None:
return False
return self.subtree(t1, t2) or self.isSubtree(t1.left, t2) or self.isSubtree(t1.right, t2)
def subtree(self, root1, root2):
if root1==None and root2==None:
return True
if root1==None or root2==None:
return False
if root1.val==root2.val:
return self.subtree(root1.left, root2.left) and self.subtree(root1.right, root2.right)
else:
return False 1
/ \
2 2
/ \ / \
3 4 4 3class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if root==None:
return True
return self.check(root, root)
def check(self, root1, root2):
if root1==None and root2==None:
return True
if root1==None or root2==None:
return False
if root1.val==root2.val:
return self.check(root1.left, root2.right) and self.check(root1.right, root2.left)
else:
return False111. Minimum Depth of Binary Tree (Easy)
树的根节点到叶子节点的最小路径长度
class Solution:
def minDepth(self, root: TreeNode) -> int:
if root==None:
return 0
left = self.minDepth(root.left)
right = self.minDepth(root.right)
if left==0 or right==0:
return left+right+1
return min(left, right) + 1404. Sum of Left Leaves (Easy)
3
/ \
9 20
/ \
15 7
There are two left leaves in the binary tree, with values 9 and 15 respectively. Return 24.class Solution:
def sumOfLeftLeaves(self, root: TreeNode) -> int:
if root==None:
return 0
val = 0
if root.left!=None:
if root.left.right==None and root.left.left==None:
val += root.left.val
val += self.sumOfLeftLeaves(root.left)
if root.right!=None:
val += self.sumOfLeftLeaves(root.right)
return val687. Longest Univalue Path (Easy)
1
/ \
4 5
/ \ \
4 4 5
Output : 2class Solution:
def longestUnivaluePath(self, root: TreeNode) -> int:
if root==None:
return 0
self.l = 0
self.helper(root)
return self.l
def helper(self, root):
if root==None:
return 0
left = self.helper(root.left)
right = self.helper(root.right)
if root.left and root.left.val == root.val:
left = 1 + left
else:
left = 0
if root.right and root.right.val == root.val:
right = 1 + right
else:
right = 0
self.l = max(self.l, right+left)
return max(left,right)337. House Robber III (Medium)
3
/ \
2 3
\ \
3 1
Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.class Solution(object):
def __init__(self):
self.map = {}
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if root==None:
return 0
if root in self.map:
return self.map[root]
val = 0
if root.left:
val += self.rob(root.left.left)
val += self.rob(root.left.right)
if root.right:
val += self.rob(root.right.left)
val += self.rob(root.right.right)
self.map[root] = max(root.val+val, self.rob(root.left) + self.rob(root.right))
return self.map[root]671. Second Minimum Node In a Binary Tree (Easy)
Input:
2
/ \
2 5
/ \
5 7
Output: 5一个节点要么具有 0 个或 2 个子节点,如果有子节点,那么根节点是最小的节点。
class Solution:
def findSecondMinimumValue(self, root: TreeNode) -> int:
if root==None:
return -1
self.min = [float('inf'),float('inf')]
self.helper(root)
if self.min[1]==float('inf'):
return -1
return self.min[1]
def helper(self,root):
if root==None:
return
if root.left and root.right:
v = min(root.left.val, root.right.val)
self.insert(v)
else:
self.insert(root.val)
self.helper(root.right)
self.helper(root.left)
def insert(self, v):
if v in self.min:
return
elif v < self.min[0]:
t = self.min[0]
self.min[0] = v
self.min[1] = t
elif v < self.min[1]:
self.min[1] = v使用 BFS 进行层次遍历。不需要使用两个队列来分别存储当前层的节点和下一层的节点,因为在开始遍历一层的节点时,当前队列中的节点数就是当前层的节点数,只要控制遍历这么多节点数,就能保证这次遍历的都是当前层的节点。
637. Average of Levels in Binary Tree (Easy)
class Solution:
def averageOfLevels(self, root: TreeNode) -> List[float]:
if root==None:
return []
ret = []
queue = [root]
while len(queue)>0:
summ = 0
cnt = len(queue)
for i in range(cnt):
node = queue.pop(0)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
summ += node.val
ret.append(summ/cnt)
return ret513. Find Bottom Left Tree Value (Easy)
Input:
1
/ \
2 3
/ / \
4 5 6
/
7
Output:
7# 两种思路,(1)从左到右层次遍历,返回最后一层第一个;(2)每层从右到左,返回最后一个
#
class Solution:
def findBottomLeftValue(self, root: TreeNode) -> int:
if root==None:
return
queue = [root]
while len(queue):
node = queue.pop(0)
if node.right:
queue.append(node.right)
if node.left:
queue.append(node.left)
return node.val 1
/ \
2 3
/ \ \
4 5 6- 层次遍历顺序:[1 2 3 4 5 6]
- 前序遍历顺序:[1 2 4 5 3 6]
- 中序遍历顺序:[4 2 5 1 3 6]
- 后序遍历顺序:[4 5 2 6 3 1]
层次遍历使用 BFS 实现,利用的就是 BFS 一层一层遍历的特性;而前序、中序、后序遍历利用了 DFS 实现。
前序、中序、后序遍只是在对节点访问的顺序有一点不同,其它都相同。
① 前序
void dfs(TreeNode root) {
visit(root);
dfs(root.left);
dfs(root.right);
}② 中序
void dfs(TreeNode root) {
dfs(root.left);
visit(root);
dfs(root.right);
}③ 后序
void dfs(TreeNode root) {
dfs(root.left);
dfs(root.right);
visit(root);
}144. Binary Tree Preorder Traversal (Medium)
class Solution:
def preorderTraversal(self, root):
stack = []
ret = []
while root or len(stack)>0:
if root:
ret.append(root.val)
stack.append(root.right)
stack.append(root.left)
root = stack.pop()
return ret94. Binary Tree Inorder Traversal (Medium)
class Solution:
def inorderTraversal(self, root):
stack, res = [], []
node = root
while node or len(stack)>0:
while node:
stack.append(node)
node = node.left
node = stack.pop()
res.append(node.val)
node = node.right
return res145. Binary Tree Postorder Traversal (Medium)
def postorderTraversal(self, root):
res, stack = [], [(root, False)]
while stack:
node, visited = stack.pop()
if node:
if visited:
# add to result if visited
res.append(node.val)
else:
# post-order
stack.append((node, True))
stack.append((node.right, False))
stack.append((node.left, False))
return res二叉查找树(BST):根节点大于等于左子树所有节点,小于等于右子树所有节点。
二叉查找树中序遍历有序。
669. Trim a Binary Search Tree (Easy)
Input:
3
/ \
0 4
\
2
/
1
L = 1
R = 3
Output:
3
/
2
/
1题目描述:只保留值在 L ~ R 之间的节点
class Solution:
def trimBST(self, root: TreeNode, L: int, R: int) -> TreeNode:
if root==None:
return
if root.val < L :
return self.trimBST(root.right, L, R)
if root.val > R:
return self.trimBST(root.left, L, R)
root.left = self.trimBST(root.left, L, R)
root.right = self.trimBST(root.right, L, R)
return root230. Kth Smallest Element in a BST (Medium)
中序遍历解法:
class Solution:
def kthSmallest(self, root: TreeNode, k: int) -> int:
self.cnt = 0
self.val = -1
def helper(root):
if root==None:
return
helper(root.left)
self.cnt += 1
if self.cnt == k:
self.val = root.val
return
helper(root.right)
helper(root)
return self.valConvert BST to Greater Tree (Easy)
Input: The root of a Binary Search Tree like this:
5
/ \
2 13
Output: The root of a Greater Tree like this:
18
/ \
20 13中序遍历思想,不过是先遍历右子树, root加上右边的。
class Solution:
def convertBST(self, root: TreeNode) -> TreeNode:
self.sum = 0
self.helper(root)
return root
def helper(self, root):
if root==None:
return
self.helper(root.right)
tmp = self.sum
self.sum += root.val
root.val += tmp
self.helper(root.left)235. Lowest Common Ancestor of a Binary Search Tree (Easy)
_______6______
/ \
___2__ ___8__
/ \ / \
0 4 7 9
/ \
3 5
For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6. Another example is LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root.val > p.val && root.val > q.val)
return lowestCommonAncestor(root.left, p, q);
if (root.val < p.val && root.val < q.val)
return lowestCommonAncestor(root.right, p, q);
return root;
}236. Lowest Common Ancestor of a Binary Tree (Medium)
_______3______
/ \
___5__ ___1__
/ \ / \
6 2 0 8
/ \
7 4
For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
if root==None or root==p or root==q:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p , q)
if left == None or right==None:
return left or right
else:
return root108. Convert Sorted Array to Binary Search Tree (Easy)
public TreeNode sortedArrayToBST(int[] nums) {
return toBST(nums, 0, nums.length - 1);
}
private TreeNode toBST(int[] nums, int sIdx, int eIdx){
if (sIdx > eIdx) return null;
int mIdx = (sIdx + eIdx) / 2;
TreeNode root = new TreeNode(nums[mIdx]);
root.left = toBST(nums, sIdx, mIdx - 1);
root.right = toBST(nums, mIdx + 1, eIdx);
return root;
}109. Convert Sorted List to Binary Search Tree (Medium)
Given the sorted linked list: [-10,-3,0,5,9],
One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:
0
/ \
-3 9
/ /
-10 5class Solution:
def sortedListToBST(self, head):
if head == None:
return None
if head.next == None:
return TreeNode(head.val)
premid = self.pre_mid(head)
mid = premid.next
midnext = mid.next
premid.next = None
t = TreeNode(mid.val)
t.left = self.sortedListToBST(head)
t.right = self.sortedListToBST(midnext)
return t
def pre_mid(self, head):
pre = head
slow = head
fast = head.next
while fast!=None and fast.next!=None:
pre = slow
slow = slow.next
fast = fast.next.next
return pre653. Two Sum IV - Input is a BST (Easy)
Input:
5
/ \
3 6
/ \ \
2 4 7
Target = 9
Output: True应该注意到,这一题不能用分别在左右子树两部分来处理这种思想,因为两个待求的节点可能分别在左右子树中。
class Solution:
def findTarget(self, root: TreeNode, k: int) -> bool:
traversed = []
flag = False
def inorder(node):
nonlocal flag
if node==None:
return None
if k-node.val in traversed:
flag = True
return
traversed.append(node.val)
inorder(node.left)
inorder(node.right)
inorder(root)
# print(flag)
if flag==True:
return True
# print(traversed)
return False530. Minimum Absolute Difference in BST (Easy)
Input:
1
\
3
/
2
Output:
1利用二叉查找树的中序遍历为有序的性质,计算中序遍历中临近的两个节点之差的绝对值,取最小值。
class Solution:
def getMinimumDifference(self, root: TreeNode) -> int:
pre = None
mindiff = float("inf")
def inorder(node):
nonlocal pre, mindiff
if node == None:
return
inorder(node.left)
if pre==None:
pre = node.val
else:
mindiff = min(mindiff, node.val-pre)
pre = node.val
# print(pre, mindiff)
inorder(node.right)
inorder(root)
return mindiff501. Find Mode in Binary Search Tree (Easy)
1
\
2
/
2
return [2].答案可能不止一个,也就是有多个值出现的次数一样多。
class Solution:
def findMode(self, root: TreeNode) -> List[int]:
max_cnt = 0
cur_cnt = 0
pre_val = None
ret = []
def inorder(root):
nonlocal max_cnt, cur_cnt, pre_val, ret
if root==None:
return
inorder(root.left)
if root.val==pre_val:
cur_cnt += 1
else:
cur_cnt = 1
if cur_cnt > max_cnt:
ret = [root.val]
max_cnt = cur_cnt
elif cur_cnt==max_cnt:
ret.append(root.val)
# print(cur_cnt, ret)
pre_val = root.val
inorder(root.right)
inorder(root)
return retTrie,又称前缀树或字典树,用于判断字符串是否存在或者是否具有某种字符串前缀。
208. Implement Trie (Prefix Tree) (Medium)
class Trie:
def __init__(self):
"""
Initialize your data structure here.
"""
self.trie = {}
def insert(self, word: str) -> None:
"""
Inserts a word into the trie.
"""
t = self.trie
for c in word:
if c not in t:
t[c] = {}
t = t[c]
t['#'] = {}
def search(self, word: str) -> bool:
"""
Returns if the word is in the trie.
"""
t = self.trie
for c in word:
if c in t:
t = t[c]
else:
return False
if '#' in t:
return True
else:
return False
def startsWith(self, prefix: str) -> bool:
"""
Returns if there is any word in the trie that starts with the given prefix.
"""
t = self.trie
for c in prefix:
if c in t:
t = t[c]
else:
return False
return TrueInput: insert("apple", 3), Output: Null
Input: sum("ap"), Output: 3
Input: insert("app", 2), Output: Null
Input: sum("ap"), Output: 5class MapSum:
def __init__(self):
"""
Initialize your data structure here.
"""
self.trie = {}
self.s = 0
def insert(self, key, val) :
t = self.trie
for c in key:
if c not in t:
t[c] = {}
t = t[c]
t['#'] = val
# print(self.trie)
def sum(self, prefix):
t = self.trie
for c in prefix:
if c not in t:
return 0
t = t[c]
# print(t)
self.s = 0
self.dfs(t)
return self.s
def dfs(self, t):
for key in t.keys():
# print(key)
if '#' == key:
self.s += t['#']
else:
self.dfs(t[key])