637.二叉树的层平均值
题目
给定一个非空二叉树, 返回一个由每层节点平均值组成的数组. 示例 1: 输入: 3 / \ 9 20 / \ 15 7 输出: [3, 14.5, 11] 解释: 第0层的平均值是 3, 第1层是 14.5, 第2层是 11. 因此返回 [3, 14.5, 11]. 注意: 节点值的范围在32位有符号整数范围内。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/average-of-levels-in-binary-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
层次遍历,得到每一层的节点总数和节点和总值计算平均值, 使用广度优先搜索。
代码
func averageOfLevels(root *TreeNode) []float64 { res := []float64{} if root == nil { return res } cnt, sum := 0, 0 // 统计节点数和节点值和 q := []*TreeNode{root} // 切片当队列使用 for len(q) > 0 { cnt = len(q) sum = 0 for i := 0; i < cnt; i++ { // 遍历当前层的节点,并将下层节点添加到队列 tmp := q[0] q = q[1:] if tmp.Left != nil { // 左子树入队 q = append(q, tmp.Left) } if tmp.Right != nil { // 右子树入队 q = append(q, tmp.Right) } sum += tmp.Val } // 计算该层的平均值 res = append(res, float64(sum) / float64(cnt)) } return res }
513. 找树左下角的值
题目
给定一个二叉树,在树的最后一行找到最左边的值。 示例 1: 输入: 2 / \ 1 3 输出: 1 示例 2: 输入: 1 / \ 2 3 / / \ 4 5 6 / 7 输出: 7 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/find-bottom-left-tree-value 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
使用深度优先搜索记录层数,每次遇到的第一个元素即是最左子树, 也可以通过广度优先搜索求解。
代码
var maxd, val int func findBottomLeftValue(root *TreeNode) int { maxd, val = 0, 0 dfs(root, 1) return val } // 深度优先搜索 func dfs(root *TreeNode, d int) { if root == nil { return } if d > maxd { maxd = d val = root.Val } if root.Left != nil { dfs(root.Left, d+1) } if root.Right != nil { dfs(root.Right, d + 1) } }
144. 二叉树的前序遍历(非递归)
题目
给定一个二叉树,返回它的 前序 遍历。 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
前序遍历: 根->左->右。 使用栈模拟递归即可, 栈用go的切片进行模拟。
代码
func preorderTraversal(root *TreeNode) []int { res := []int{} stack :=[]*TreeNode{root} // 使用切片模拟栈 for len(stack) > 0 { // 切片模拟出栈 s := stack[len(stack) - 1] stack = stack[:len(stack) - 1] if s == nil { continue } res = append(res, s.Val) // 右子树先入栈,保证先出栈的为左子树 stack = append(stack, s.Right) stack = append(stack, s.Left) } return res }
145.非递归实现二叉树的后序遍历
题目
给定一个二叉树,返回它的 后序 遍历。 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
后序遍历左->右->根, 等价于根->右->左遍历后结果的翻转。修改非递归实现的先序遍历代码的左右子树的入栈顺序,再将结果进行一次翻转即可得到结果。
代码
// 非递归实现二叉树的后序遍历 func postorderTraversal(root *TreeNode) []int { // 非递归实现二叉树的后序遍历 res := []int{} stack :=[]*TreeNode{root} // 使用切片模拟栈 for len(stack) > 0 { // 切片模拟出栈 s := stack[len(stack) - 1] stack = stack[:len(stack) - 1] if s == nil { continue } res = append(res, s.Val) stack = append(stack, s.Left)// 左子树先入栈, 保证右子树先出站 stack = append(stack, s.Right) } res = reverses(res) return res } // 切片翻转 func reverses(s []int) []int { for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { s[i], s[j] = s[j], s[i] } return s }
94.非递归实现二叉树的中序遍历
题目
给定一个二叉树,返回它的中序 遍历。 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
二叉树的中序遍历, 左根右。
先将左子树全部进栈,然后取栈顶元素进行输出,接着右子树开始进栈。
代码
// 非递归实现二叉树的中序遍历 func inorderTraversal(root *TreeNode) []int { res := []int{} if root == nil { return res } stack := []*TreeNode{} cur := root for cur != nil || len(stack) > 0 { for cur != nil { // 先将左子树进栈 stack = append(stack, cur) cur = cur.Left } // 取栈顶元素,即为根 node := stack[len(stack)-1] stack = stack[:len(stack)-1] res = append(res, node.Val) // 遍历右子树 cur = node.Right } return res }
669.修剪二叉搜索树
题目
给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。 示例 1: 输入: 1 / \ 0 2 L = 1 R = 2 输出: 1 \ 2 示例 2: 输入: 3 / \ 0 4 \ 2 / 1 L = 1 R = 3 输出: 3 / 2 / 1 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/trim-a-binary-search-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
二叉搜索树是具有有以下性质的二叉树:
- 若左子树不为空,则左子树上所有节点的值均小于或等于它的根节点的值。
- 若右子树不为空,则右子树上所有节点的值均大于或等于它的根节点的值。
- 左、右子树也分别为二叉搜索树。
修剪操作, 如当前节点的指针指向左子树,需要将左子树剪掉,将当前节点的指针指向左子树的子节点上,以此类推。
代码
func trimBST(root *TreeNode, L int, R int) *TreeNode { if root == nil { return nil } if root.Val > R { return trimBST(root.Left, L, R) } if root.Val < L { return trimBST(root.Right, L, R) } root.Left = trimBST(root.Left, L, R) root.Right = trimBST(root.Right, L, R) return root }
230. 二叉搜索中第k小的元素
题目
给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。 说明: 你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。 示例 1: 输入: root = [3,1,4,null,2], k = 1 3 / \ 1 4 \ 2 输出: 1 示例 2: 输入: root = [5,3,6,2,4,null,null,1], k = 3 5 / \ 3 6 / \ 2 4 / 1 输出: 3 进阶: 如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k 小的值,你将如何优化 kthSmallest 函数? 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
二叉搜索树使用中序遍历, 第k个就是结果, 使用递归解法。
代码
// 求二叉搜索树第k小的元素 func kthSmallest(root *TreeNode, k int) int { leftCnt := count(root.Left) if leftCnt == k - 1 { return root.Val } if leftCnt > k - 1 { return kthSmallest(root.Left, k) } return kthSmallest(root.Right, k - leftCnt - 1) } func count(node *TreeNode) int { if node == nil { return 0 } return 1 + count(node.Left) + count(node.Right) }
235.二叉搜索树的最近公共祖先
题目
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” 例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5] 示例 1: 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点 2 和节点 8 的最近公共祖先是 6。 示例 2: 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 输出: 2 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
- 两个节点分别在左右子树,公共祖先是根节点;
- 两个节点都在左子树;
- 两个节点都在右子树;
代码
//求二叉搜索树的最近公共祖先 func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { 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.二叉树的最近公共祖先
题目
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” 例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4] 示例 1: 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出: 3 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。 示例 2: 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出: 5 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。 说明: 所有节点的值都是唯一的。 p、q 为不同节点且均存在于给定的二叉树中。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
- 如果该节点就是子节点的其中之一,且能够通过该节点找到另一个子节点,那么这个节点就是最近公共祖先;
- 如果通过该节点不能找到两个子节点的,不是公共祖先,需要往上找;
- 如果通过该节点能找到两个子节点的,且分别位于其左子树或右子树上的,其就是最近公共祖先。
- 如果通过该节点能找到两个子节点的,且全部位于左子树或者右子树上的,是公共祖先,但不是最近的公共祖先,需要继续往下找。
代码
// 求二叉树的最近公共祖先 func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { if root == nil || root == p || root == q { return root } left := lowestCommonAncestor(root.Left, p, q) right := lowestCommonAncestor(root.Right, p, q) if left != nil && right != nil { return root } if left != nil { return left } return right }
653.两数之和IV-输入BST
题目
给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。 案例 1: 输入: 5 / \ 3 6 / \ \ 2 4 7 Target = 9 输出: True 案例 2: 输入: 5 / \ 3 6 / \ \ 2 4 7 Target = 28 输出: False 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
- 二叉查找树进行中序遍历,得到的序列是有序的,
- 再利用双指针进行求解即可。
代码
// 在二叉树中查找两个节点使之和等于k func findTarget(root *TreeNode, k int) bool { nums := []int{} toArray(root, &nums) i, j := 0, len(nums) - 1 for i < j { sum := nums[i] + nums[j] if sum == k { return true } if sum < k { i++ }else { j-- } } return false } // 二叉查找树中序遍历后得到一个有序数组 func toArray(root *TreeNode, arr *[]int){ if root == nil { return } toArray(root.Left, arr) *arr = append(*arr, root.Val) toArray(root.Right, arr) }