二叉树基础知识
可以点击这篇《go实现”二叉树遍历“》复习二叉树相关的知识点。
144. 二叉树的前序遍历
解题思路:
二叉树里的先:指的是中间节点遍历的顺序
中间节点先遍历,先序遍历
中间节点在中间,中序遍历
中间节点在最后,后序遍历
go语言里有点小坑,数组传递时候要传递地址。如果不传递数组地址,那么要覆盖当前数组值。
不传地址的方式
func preorderTraversal(root *TreeNode) []int {
r := make([]int, 0, 4)
return traversal(root, r)
}
func traversal(node *TreeNode, vals []int) []int {
if node == nil {
return vals
}
vals = append(vals, node.Val)
vals = traversal(node.Left, vals)
vals = traversal(node.Right, vals)
return vals
}
传递地址的方式
func preorderTraversal(root *TreeNode) []int {
r := make([]int, 0, 4)
return *traversal(root, &r)
}
func traversal(node *TreeNode, vals *[]int) *[]int {
if node == nil {
return vals
}
*vals = append(*vals, node.Val)
traversal(node.Left, vals)
traversal(node.Right, vals)
return vals
}
226. 翻转二叉树
解题思路:
和二叉树遍历是一样的,只不过这里换成子节点的对换
func invertTree(root *TreeNode) *TreeNode {
if root == nil {
return root
}
stack := []*TreeNode{}
stack = append(stack, root)
for len(stack) > 0 {
node := stack[len(stack)-1]
stack = stack[:len(stack) - 1]
if node != nil {
node.Left, node.Right = node.Right, node.Left
stack = append(stack, node.Left)
stack = append(stack, node.Right)
}
}
return root
}
104. 二叉树的最大深度
解题思路:
本题可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。
- 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
- 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始)
func maxDepth(root *TreeNode) int {
if root == nil {
return 0
}
return max(maxDepth(root.Left), maxDepth(root.Right)) + 1
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
110. 平衡二叉树
解题思路:
平衡二叉树需要满足的条件:
1. 左子树和右子树的高度差要 <= 1
2. 任意节点都要满足这个条件
那么这个题用递归分别求左右子树高度即可
func isBalanced(root *TreeNode) bool {
// 如果是空左右子树都为空,高度差肯定<=1符合条件了
if root == nil {
return true
}
// 1. 递归求解左子树和右子树高度并判断高度差是否符合要求
// 2. 任意一个节点都要满足左右子树高度差<=1
return abs(height(root.Left) - height(root.Right)) <= 1 && isBalanced(root.Left) && isBalanced(root.Right)
}
func height(root *TreeNode) int {
// 如果为空,那么这个节点高度为0
if root == nil {
return 0
}
// 求解当前节点左右子树的高度差
return max(height(root.Left), height(root.Right)) + 1
}
func abs(x int) int {
if x < 0 {
return -1 * x
}
return x
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
654. 最大二叉树
解题思路
1. 创建树一般使用前序遍历(先填充根节点)
func constructMaximumBinaryTree(nums []int) *TreeNode {
if len(nums) == 0 {
return nil
}
best := 0
for i := range nums {
if nums[i] > nums[best] {
best = i
}
}
// go的数组为左闭右开
return &TreeNode{nums[best], constructMaximumBinaryTree(nums[:best]), constructMaximumBinaryTree(nums[best+1:])}
}
单调栈解法:
func constructMaximumBinaryTree(nums []int) *TreeNode {
tree := make([]*TreeNode, len(nums)) // 可以认为是一个缓存,key是栈保存的数组索引
stk := []int{} // 栈结构,记录索引
for i, num := range nums {
// 根据当前遍历值生成一个新节点
tree[i] = &TreeNode{Val: num}
// 和栈上的值对比,如果当前值大于栈顶顶值,栈顶节点应该作为当前节点的左子树
for len(stk) > 0 && num > nums[stk[len(stk)-1]] {
tree[i].Left = tree[stk[len(stk)-1]]
stk = stk[:len(stk)-1] // 从栈顶弹出
}
// 如果栈顶数据大于当前值,当前值把当前新节点挂到栈顶节点右侧
if len(stk) > 0 {
tree[stk[len(stk)-1]].Right = tree[i]
}
// 新索引位置
stk = append(stk, i)
}
return tree[stk[0]]
}
530. 二叉搜索树的最小绝对差
func getMinimumDifference(root *TreeNode) int {
var ans, pre = math.MaxInt64, -1
var dfs func(*TreeNode)
dfs = func(node *TreeNode) {
if node == nil {
return
}
dfs(node.Left)
if pre != -1 && node.Val - pre < ans {
ans = node.Val - pre
}
pre = node.Val
dfs(node.Right)
}
dfs(root)
return ans
}