首页 > 编程语言 >算法练习-第十五天【二叉树】

算法练习-第十五天【二叉树】

时间:2022-10-11 01:33:06浏览次数:68  
标签:Right TreeNode cur 第十五天 queue 算法 二叉树 root Left

二叉树

226. 翻转二叉树

参考:代码随想录

思路

翻转二叉树的方式:

  1. 递归
  2. 迭代法
  3. 层序遍历

1.递归

前序遍历

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
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
}

后序遍历

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func invertTree(root *TreeNode) *TreeNode {
	if root == nil {
		return root
	}
	// 递归后序遍历
	invertTree(root.Left)
	invertTree(root.Right)
	root.Left, root.Right = root.Right, root.Left

	return root
}

中序遍历
因为中序遍历的顺序是左中右,按照前后序的方式来处理的话会导致节点多次反转的问题。
解决办法:左子树翻转一次后回退到中间节点,中间节点再次翻转,此时的左子树变成了右子树,右子树变成了左子树,此时只需要再处理一次左子树(翻转前的右子树)。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func invertTree(root *TreeNode) *TreeNode {
	if root == nil {
		return root
	}
	// 递归中序遍历
	invertTree(root.Left)
	root.Left, root.Right = root.Right, root.Left
	invertTree(root.Left)

	return root
}

2.迭代法

以下代码使用前序遍历的方式,后序遍历也类似。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func invertTree(root *TreeNode) *TreeNode {
	// 前序遍历
	if root == nil {
		return root
	}
	stack := list.New()
	stack.PushBack(root)
	for stack.Len() > 0 {
		e := stack.Back()
		if e.Value != nil {
			cur := e.Value.(*TreeNode)
			stack.Remove(e)
			if cur.Right != nil {
				stack.PushBack(cur.Right)
			}
			if cur.Left != nil {
				stack.PushBack(cur.Left)
			}
			stack.PushBack(cur)
			stack.PushBack(nil)
		} else {
			stack.Remove(e)
			cur := stack.Remove(stack.Back()).(*TreeNode)
			cur.Left, cur.Right = cur.Right, cur.Left
		}
	}

	return root
}

3.层序遍历

使用层序遍历,翻转每一层的各个节点

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func invertTree(root *TreeNode) *TreeNode {
	if root == nil {
		return root
	}
	queue := list.New()
	queue.PushBack(root)
	for queue.Len() > 0 {
		length := queue.Len()
		// 处理每一层的各个节点
		for ; length > 0; length-- {
			cur := queue.Remove(queue.Front()).(*TreeNode)
			cur.Left, cur.Right = cur.Right, cur.Left // 交换
			if cur.Left != nil {
				queue.PushBack(cur.Left)
			}
			if cur.Right != nil {
				queue.PushBack(cur.Right)
			}
		}
	}

	return root
}

总结

翻转二叉树可以有多种实现方式,递归的方式容易理解和实现。但是不建议使用中序遍历容易造成错误。
迭代的方法中可以模拟深度优先搜索和广度优先搜索。

101. 对称二叉树

参考:代码随想录

思路

判断二叉树是否对称,需要将树的左子树的左节点与右子树的右节点对比,左子树的右节点与右子树的左节点进行对比。
使用递归

  1. 确定递归函数参数与返回值func dfs(left *TreeNode, right *TreeNode) bool
  2. 确定递归终止条件
    • 左右节点都为空,则true
    • 左右有一个不为空,则false
    • 左右都不为空,但数值不相等
  3. 单层递归逻辑
    • 比较左子树的左节点与右子树的右节点
    • 比较左子树的右节点与右子树的左节点
    • 左右都为true, 返回true, 否则false

递归

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSymmetric(root *TreeNode) bool {
	return dfs(root.Left, root.Right)
}

func dfs(left *TreeNode, right *TreeNode) bool {
	// 左子树为空 右子树为空
	if left == nil && right == nil {
		return true
	}
	if left == nil || right == nil {
		return false
	}
	if left.Val != right.Val {
		return false
	}

	outer := dfs(left.Left, right.Right) // 左子树: 左	右子树: 右
	inner := dfs(left.Right, right.Left) // 左子树: 右	右子树: 左

	return outer && inner // 左子树: 中 	右子树: 中
}

迭代法

使用队列判断左右子树是否相等

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSymmetric(root *TreeNode) bool {
	if root == nil {
		return false
	}
	queue := list.New()
	queue.PushBack(root.Left)
	queue.PushBack(root.Right)
	for queue.Len() > 0 {
		//从队列中取出
		leftNode := queue.Remove(queue.Front()).(*TreeNode)
		rightNode := queue.Remove(queue.Front()).(*TreeNode)
		if leftNode == nil && rightNode == nil { // 此时对称
			continue
		}
		if leftNode == nil || rightNode == nil || (leftNode.Val != rightNode.Val) {
			return false
		}
		queue.PushBack(leftNode.Left)   // 加入左节点左孩子
		queue.PushBack(rightNode.Right) // 加入右节点右孩子
		queue.PushBack(rightNode.Left)  // 加入右节点左孩子
		queue.PushBack(leftNode.Right)  // 加入左节点右孩子
	}
	return true
}

总结

以上代码不是最简单的形式,但是思路比较清晰易于理解。迭代法就是将左右子树依次放到队列中,然后依次取出进行比对。按照此思路使用栈也是可以处理的。

标签:Right,TreeNode,cur,第十五天,queue,算法,二叉树,root,Left
From: https://www.cnblogs.com/neilliu/p/16777906.html

相关文章

  • 数据算法--Hadoop-Spark大数据处理技巧 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1SCA5hN-0ZbEK_uHZgpBkVg点击这里获取提取码 ......
  • 算法导论第2版 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1yq65hvfK-ooqx-uuYX1CLg点击这里获取提取码 ......
  • 算法图解 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1li7LmqlOKZJV_BYO9iJbYA点击这里获取提取码 ......
  • 算法导论中文第三版 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1CugZiIojOfb4S_qB85hamw点击这里获取提取码 ......
  • 加密算法总结
    1.加密算法的分类根本不考虑解密问题;私用密钥加密技术:对称式加密(SymmetricKeyEncryption):对称式加密方式对加密和解密使用相同的密钥。通常,这种加密方式在应用中难以实施,......
  • 算法练习-第十四天【二叉树】
    二叉树的遍历144.二叉树的前序遍历参考:代码随想录-二叉树的递归遍历参考:代码随想录-二叉树的迭代遍历参考:代码随想录-二叉树的迭代遍历统一写法思路-递归法二叉树的......
  • 回溯算法 组合问题(一)
    题目来自leetcode77题给定两个整数n和k,返回范围[1,n]中所有可能的k个数的组合。你可以按任何顺序返回答案。示例1:输入:n=4,k=2输出:[[2,4],[3,4],......
  • 牛客网高频算法题系列-BM19-寻找峰值
    牛客网高频算法题系列-BM19-寻找峰值题目描述给定一个长度为n的数组nums,请你找到峰值并返回其索引。数组可能包含多个峰值,在这种情况下,返回任何一个所在位置即可。峰......
  • 学习常用模型及算法1.模拟退火算法
    title:学习常用模型及算法1.模拟退火算法excerpt:学习数学建模常用模型及算法tags:[数学建模,matlab]categories:[学习,数学建模]index_img:https://picture-......
  • 学习常用模型及算法4.元胞自动机
    title:学习常用模型及算法4.元胞自动机excerpt:学习数学建模常用模型及算法tags:[数学建模,matlab]categories:[学习,数学建模]index_img:https://picture-st......