目录
具体:
112. 路径总和
DFS
首先是 DFS 解法,该解法的想法是一直向下找到叶子节点,如果到叶子节点时sum == 0
,说明找到了一条符合要求的路径。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def hasPathSum(self, root: TreeNode, sum: int) -> bool:
if not root:
return False
if sum == root.val and not root.left and not root.right:
return True
left = self.hasPathSum(root.left, sum - root.val)
right = self.hasPathSum(root.right, sum - root.val)
return left or right
栈
除了上面的 队列 解法以外,也可以使用 栈,同时保存节点和到这个节点的路径和。但是这个解法已经不是 BFS。因为会优先访问 后进来 的节点,导致会把根节点的右子树访问结束之后,才访问左子树。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def hasPathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: bool
"""
if not root:
return False
stack = []
stack.append((root, root.val))
while stack:
node, path = stack.pop()
if not node.left and not node.right and path == sum:
return True
if node.left:
stack.append((node.left, path + node.left.val))
if node.right:
stack.append((node.right, path + node.right.val))
return False
113. 路径总和 II
DFS
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
li = []
if root is None:
return li
def find(root,sum,path):
sum-=root.val
if root.left is None and root.right is None and sum==0:
li.append(path+[root.val])
if root.left:
find(root.left,sum,path+[root.val])
if root.right:
find(root.right,sum,path+[root.val])
find(root,sum,[])
return li
437. 路径总和 III
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# 精简版,五行代码不解释
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> int:
def dfs(root, sumlist):
if root is None: return 0
sumlist = [num + root.val for num in sumlist] + [root.val]
return sumlist.count(sum) + dfs(root.left, sumlist) + dfs(root.right, sumlist)
return dfs(root, [])
# 展开版,易理解
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> int:
def dfs(root, sumlist):
if root is None:
return 0
sumlist = [num+root.val for num in sumlist]
sumlist.append(root.val)
count = 0
for num in sumlist:
if num == sum:
count += 1
# count = sumlist.count(sum)
return count + dfs(root.left, sumlist) + dfs(root.right, sumlist)
return dfs(root, [])
124. 二叉树中的最大路径和
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def maxPathSum(self, root: TreeNode) -> int:
self.sum = float("-inf")
def dfs(node):
if not node: return 0
l = dfs(node.left)
r = dfs(node.right)
self.sum = max(self.sum,max(l,0)+max(r,0)+node.val)
return max(0,l,r) + node.val
dfs(root)
return self.sum
99. 恢复二叉搜索树
# 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 recoverTree(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
nodes = []
# 中序遍历二叉树,并将遍历的结果保存到list中
def dfs(root):
if not root:
return
dfs(root.left)
nodes.append(root)
dfs(root.right)
dfs(root)
x = None
y = None
pre = nodes[0]
# 扫面遍历的结果,找出可能存在错误交换的节点x和y
for i in range(1,len(nodes)):
if pre.val>nodes[i].val:
y=nodes[i]
if not x:
x = pre
pre = nodes[i]
# 如果x和y不为空,则交换这两个节点值,恢复二叉搜索树
if x and y:
x.val,y.val = y.val,x.val
222. 完全二叉树的节点个数
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def countNodes(self, root: TreeNode) -> int:
if root == None:
return 0
if root.left is None and root.right is None:
return 1
return self.countNodes(root.left) + self.countNodes(root.right) + 1
102. 二叉树的层序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
res = []
queue = [root]
while queue:
# 获取当前队列的长度,这个长度相当于 当前这一层的节点个数
size = len(queue)
tmp = []
# 将队列中的元素都拿出来(也就是获取这一层的节点),放到临时list中
# 如果节点的左/右子树不为空,也放入队列中
for _ in range(size):
r = queue.pop(0)
tmp.append(r.val)
if r.left:
queue.append(r.left)
if r.right:
queue.append(r.right)
# 将临时list加入最终返回结果中
res.append(tmp)
return res
96. 不同的二叉搜索树
代码:
class Solution:
def numTrees(self, n):
"""
:type n: int
:rtype: int
"""
G = [0]*(n+1)
G[0], G[1] = 1, 1
for i in range(2, n+1):
for j in range(1, i+1):
G[i] += G[j-1] * G[i-j]
return G[n]
class Solution {
public:
int numTrees(int n) {
vector<int> G(n + 1, 0);
G[0] = 1;
G[1] = 1;
for (int i = 2; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
G[i] += G[j - 1] * G[i - j];
}
}
return G[n];
}
};
95. 不同的二叉搜索树 II
递归:
class Solution {
public:
vector<TreeNode*> generateTrees(int start, int end) {
if (start > end) {
return { nullptr };
}
vector<TreeNode*> allTrees;
// 枚举可行根节点
for (int i = start; i <= end; i++) {
// 获得所有可行的左子树集合
vector<TreeNode*> leftTrees = generateTrees(start, i - 1);
// 获得所有可行的右子树集合
vector<TreeNode*> rightTrees = generateTrees(i + 1, end);
// 从左子树集合中选出一棵左子树,从右子树集合中选出一棵右子树,拼接到根节点上
for (auto& left : leftTrees) {
for (auto& right : rightTrees) {
TreeNode* currTree = new TreeNode(i);
currTree->left = left;
currTree->right = right;
allTrees.emplace_back(currTree);
}
}
}
return allTrees;
}
vector<TreeNode*> generateTrees(int n) {
if (!n) {
return {};
}
return generateTrees(1, n);
}
};
# 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 generateTrees(self, n: int) -> List[TreeNode]:
if not n:
return []
memo = {}
def generate(s, e):
if s > e:
return [None]
if (s, e) in memo:
return memo[(s, e)]
res = []
for i in range(s, e + 1):
left = generate(s, i - 1)
right = generate(i + 1, e)
for l in left:
for r in right:
root = TreeNode(i)
root.left = l
root.right = r
res.append(root)
memo[(s, e)] = res
return res
return generate(1, n)
98. 验证二叉搜索树
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
stack, inorder = [], float('-inf')
while stack or root:
while root:
stack.append(root)
root = root.left
root = stack.pop()
# 如果中序遍历得到的节点的值小于等于前一个 inorder,说明不是二叉搜索树
if root.val <= inorder:
return False
inorder = root.val
root = root.right
return True
class Solution {
public:
bool isValidBST(TreeNode* root) {
stack<TreeNode*> stack;
long long inorder = (long long)INT_MIN - 1;
while (!stack.empty() || root != nullptr) {
while (root != nullptr) {
stack.push(root);
root = root -> left;
}
root = stack.top();
stack.pop();
// 如果中序遍历得到的节点的值小于等于前一个 inorder,说明不是二叉搜索树
if (root -> val <= inorder) return false;
inorder = root -> val;
root = root -> right;
}
return true;
}
};
101. 对称二叉树
同剑指offer 58题:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
return self.isSym(root, root)
def isSym(self, tree1, tree2):
if tree1 == None and tree2 == None:
return True
if tree1 == None or tree2 == None:
return False
if tree1.val != tree2.val:
return False
return self.isSym(tree1.left, tree2.right) and self.isSym(tree1.right, tree2.left)
104. 二叉树的最大深度
同剑指offer 38题:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if root == None:
return 0
count = max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
return count
114. 二叉树展开为链表
# 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 flatten(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
if not root:
return
stack = [root]
prev = None
while stack:
curr = stack.pop()
if prev:
prev.left = None
prev.right = curr
left, right = curr.left, curr.right
if right:
stack.append(right)
if left:
stack.append(left)
prev = curr
class Solution {
public:
void flatten(TreeNode* root) {
if (root == nullptr) {
return;
}
auto stk = stack<TreeNode*>();
stk.push(root);
TreeNode *prev = nullptr;
while (!stk.empty()) {
TreeNode *curr = stk.top(); stk.pop();
if (prev != nullptr) {
prev->left = nullptr;
prev->right = curr;
}
TreeNode *left = curr->left, *right = curr->right;
if (right != nullptr) {
stk.push(right);
}
if (left != nullptr) {
stk.push(left);
}
prev = curr;
}
}
};
208. 实现 Trie (前缀树)
class TrieNode:
def __init__(self):
self.children = defaultdict(TrieNode)
self.is_word = False
class Trie:
def __init__(self):
"""
Initialize your data structure here.
"""
self.root = TrieNode()
def insert(self, word: str) -> None:
"""
Inserts a word into the trie.
"""
node = self.root
for s in word:
node = node.children[s]
node.is_word = True
def search(self, word: str) -> bool:
"""
Returns if the word is in the trie.
"""
node = self.root
for s in word:
if s in node.children:
node = node.children[s]
else:
return False
return node.is_word
def startsWith(self, prefix: str) -> bool:
"""
Returns if there is any word in the trie that starts with the given prefix.
"""
node = self.root
for s in prefix:
if s in node.children:
node = node.children[s]
else:
return False
return True
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)