-
513找树左下角的值
- 代码随想录 (programmercarl.com)
-
第一印象
- 按照行来找值,那么可以使用层序遍历,每次更新最左面的值。最后保留的就是最后一行的最左面的值。
-
讲解观后感
- 用递归法来做的话,就需要一个参数来记录深度,并且要选择左在先的递归法,这样在深度更新时存入的节点数值就是最左面的值。
-
解题代码
- 层序
-
func findBottomLeftValue(root *TreeNode) int {
st := list.New()
ans := 0
if root!=nil {
st.PushBack(root)
}
for st.Len()!=0 {
len := st.Len()
for i:=0;i<len;i++ {
node := st.Remove(st.Front()).(*TreeNode)
if i==0 {
ans = node.Val
}
if node.Left!=nil {
st.PushBack(node.Left)
}
if node.Right!=nil {
st.PushBack(node.Right)
}
}
}
return ans
}
- 递归
-
var depth int
var res int
func findBottomLeftValue(root *TreeNode) int {
depth, res = 0, 0
dfs(root, 1)
return res
}
func dfs(root *TreeNode, d int) {
if root == nil {
return
}
if root.Left == nil && root.Right == nil && depth < d {
depth = d
res = root.Val
}
dfs(root.Left, d+1)
dfs(root.Right, d+1)
}
- 递归回溯表达(C++)
-
class Solution {
public:
int maxDepth = INT_MIN
int result
void traversal(TreeNode* root, int depth) {
if (root->left == NULL && root->right == NULL) {
if (depth > maxDepth) {
maxDepth = depth
result = root->val
}
return
}
if (root->left) {
depth++
traversal(root->left, depth)
depth--
}
if (root->right) {
depth++
traversal(root->right, depth)
depth--
}
return
}
int findBottomLeftValue(TreeNode* root) {
traversal(root, 0)
return result
}
}
-
112路径总和113路径总和II
- 代码随想录 (programmercarl.com)
-
第一印象
- 使用回溯遍历所有叶子结点并计算值(保存路径)
-
遇到问题
-
var ans [][]int
func pathSum(root *TreeNode, targetSum int) [][]int {
ans = make([][]int, 0)
path := []int{}
if root==nil {
return ans
}
serchPath(root, 0, path, targetSum)
return ans
}
func serchPath(node *TreeNode, sum int,path []int, targetSum int) {
sum+=node.Val
path = append(path, node.Val)
if node.Left==nil&&node.Right==nil {
if sum==targetSum {
ans = append(ans, path)
}
return
}
if node.Left!=nil {
serchPath(node.Left, sum, path, targetSum)
}
if node.Right!=nil {
serchPath(node.Right, sum, path, targetSum)
}
return
}
- 原因:
不能直接将Path放到ans里面, 因为Path是共享的, 每次遍历子树时都会被修改
-
解题代码
-
var ans [][]int
func pathSum(root *TreeNode, targetSum int) [][]int {
ans = make([][]int, 0)
path := []int{}
if root==nil {
return ans
}
serchPath(root, 0, path, targetSum)
return ans
}
func serchPath(node *TreeNode, sum int,path []int, targetSum int) {
sum+=node.Val
path = append(path, node.Val)
if node.Left==nil&&node.Right==nil {
if sum==targetSum {
copyPath := make([]int, len(path))
for i:=0;i<len(path);i++ {
copyPath[i] = path[i]
}
ans = append(ans, copyPath)
}
return
}
if node.Left!=nil {
serchPath(node.Left, sum, path, targetSum)
}
if node.Right!=nil {
serchPath(node.Right, sum, path, targetSum)
}
return
}
-
105、106构造二叉树
- 代码随想录 (programmercarl.com)
-
讲解观后感
- 方法是利用后序数组寻找中结点,然后通过中序数组中结点的位置分出左右两个数组,后序根据其长度来区分,再寻找其各自的中结点。用递归实现。
- 需要注意用中序和后序、前序和中序数组都可以构造出唯一的树,但是用前序和后序不能。因为无法无法确定左右子树的分界。
-
解题代码
- golang中可以利用map存储中序遍历的值与位置,方便构建时查找。
- 中序与后序
-
var (
hash map[int]int
)
func buildTree(inorder []int, postorder []int) *TreeNode {
hash = make(map[int]int)
for i, v := range inorder {
hash[v] = i
}
root := rebuild(inorder, postorder, len(postorder)-1, 0, len(inorder)-1)
return root
}
func rebuild(inorder []int, postorder []int, rootIdx int, l, r int) *TreeNode {
if l > r {
return nil
}
if l == r {
return &TreeNode{Val : inorder[l]}
}
rootV := postorder[rootIdx]
rootIn := hash[rootV]
root := &TreeNode{Val : rootV}
root.Left = rebuild(inorder, postorder, rootIdx-(r-rootIn)-1, l, rootIn-1)
root.Right = rebuild(inorder, postorder, rootIdx-1, rootIn+1, r)
return root
}
- 前序与中序
-
var (
hash map[int]int
)
func buildTree(preorder []int, inorder []int) *TreeNode {
hash = make(map[int]int, len(inorder))
for i, v := range inorder {
hash[v] = i
}
root := build(preorder, inorder, 0, 0, len(inorder)-1)
return root
}
func build(pre []int, in []int, root int, l, r int) *TreeNode {
if l > r {
return nil
}
rootVal := pre[root]
index := hash[rootVal]
node := &TreeNode {Val: rootVal}
node.Left = build(pre, in, root + 1, l, index-1)
node.Right = build(pre, in, root + (index-l) + 1, index+1, r)
return node
}