递归遍历这两颗二叉树,判断每个节点,只要存在值不同时就不是相同的树。
func isSameTree(p *TreeNode, q *TreeNode) bool {
if p == nil && q == nil {
return true
}
if p == nil || q == nil {
return false
}
if p.Val != q.Val {
return false
}
return isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
}
根据镜像的定义,如果这是一个镜像二叉树,那只要把根节点去掉之后可以看做是两个完全对称的二叉树。
所以跟上一题做法基本一致,递归遍历每个子节点,只不过判断时不是左对左、右对右的判断,而是对称判断,即左对右,右对左,只要完全一致,则是对称的二叉树。
func isSame(a, b *TreeNode) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}
return a.Val == b.Val && isSame(a.Left, b.Right) && isSame(a.Right, b.Left)
}
func isSymmetric(root *TreeNode) bool {
if root == nil {
return true
}
return isSame(root.Left, root.Right)
}
同样递归遍历两个树,左对左,右对右,将值相加后赋给新的树节点即可。
注意判断节点为空时,直接取另一颗树对应结点赋值即可。
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
if root1 == nil && root2 == nil {
return nil
}
if root1 == nil {
return root2
}
if root2 == nil {
return root1
}
newTree := &TreeNode{
Val : root1.Val + root2.Val,
Left : mergeTrees(root1.Left, root2.Left),
Right : mergeTrees(root1.Right, root2.Right),
}
return newTree
}
func binaryTreePaths(root *TreeNode) (res []string) {
if root == nil {
return nil
}
var a func(*TreeNode, string)
a = func(node *TreeNode, path string) {
if node == nil {
return
}
str := fmt.Sprintf("%d", node.Val)
path = path+str
// 叶子节点
if node.Left == nil && node.Right == nil {
res = append(res, path)
return
}
a(node.Left, path+"->")
a(node.Right, path+"->")
}
a(root, "")
return
}
路径总和向下传递的时候减去当前节点的值,这样只要判断是叶子节点并且叶子节点的值等于当时的参数路径总和即代表存在目标路径。
func hasPathSum(root *TreeNode, targetSum int) bool {
if root == nil {
return false
}
if root.Left == nil && root.Right == nil && root.Val == targetSum {
return true
}
return hasPathSum(root.Left, targetSum-root.Val) || hasPathSum(root.Right, targetSum-root.Val)
}
func pathSum(root *TreeNode, targetSum int) (res [][]int) {
if root == nil {
return
}
arr := []int{}
var a func(*TreeNode, int)
a = func (node *TreeNode, sum int) {
if node == nil {
return
}
sum -= node.Val
arr = append(arr, node.Val)
// 从最左叶子节点开始往回遍历时,将该节点从arr中取出
// 这样能确保arr中的节点数组是从根节点到当前节点的路径节点
defer func() { arr = arr[:len(arr)-1] }()
// 找到一条路径
if node.Left == nil && node.Right == nil && sum == 0 {
// append([]int{}, arr...) 将arr的元素都放在一个新的切片中加入到res,
// 否则如果直接将arr将入到res,后面对arr的修改都会同步到res中
res = append(res, append([]int{}, arr...))
return
}
a(node.Left, sum)
a(node.Right, sum)
}
a(root, targetSum)
return
}
只需要将每个节点的左右节点互换即可完成翻转。
func invertTree(root *TreeNode) *TreeNode {
if root == nil {
return root
}
root.Left, root.Right = root.Right, root.Left
invertTree(root.Left)
invertTree(root.Right)
return root
}