public IList<int?> InorderTraversal(TreeNode root)
{
List<int?> result = new List<int?>();
if (root.val == null)
{
return result;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode current = root;
while (stack.Any() || current != null)
{
while (current is { val: not null })
{
stack.Push(current);
current = current.left;
}
current = stack.Pop();
result.Add(current.val);
current = current.right;
}
return result;
}
后序非递归
public IList<int?> PostorderTraversal(TreeNode root)
{
List<int?> result = new List<int?>();
if (root.val == null)
{
return result;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.Push(root);
while (stack.Any())
{
TreeNode temp = stack.Pop();
result.Add(temp.val);
if (temp.left != null)
{
stack.Push(temp.left);
}
if (temp.right != null)
{
stack.Push(temp.right);
}
}
return Enumerable.Reverse(result).ToList();
}
DFS 和 BFS
DFS 深度优先搜索-从上到下
// V1:深度遍历,结果指针作为参数传入到函数内部
public IList<int?> DFS_Traversal(TreeNode root)
{
List<int?> result = new List<int?>();
DFS(root, ref result);
return result;
}
void DFS(TreeNode p, ref List<int?> result)
{
if (p.val == null)
{
return;
}
result.Add(p.val);
if (p.left != null)
{
DFS(p.left, ref result);
}
if (p.right != null)
{
DFS(p.right, ref result);
}
}
DFS 深度优先搜索-从下向上(分治法)
// V2:通过分治法遍历
public IList<int?> DFS_Traversal_Divide(TreeNode root)
{
IList<int?> result = DivideAndConquer(root);
return result;
}
IList<int?> DivideAndConquer(TreeNode? p)
{
List<int?> result = new List<int?>();
if (p?.val == null)
{
return result;
}
// 分治(Divide)
IList<int?> left = DivideAndConquer(p.left);
IList<int?> right = DivideAndConquer(p.right);
// 合并结果(Conquer)
result.Add(p.val);
result.AddRange(left);
result.AddRange(right);
return result;
}
public IList<int?> BinaryTreePaths_BFS(TreeNode root)
{
List<int?> result = new List<int?>();
if (root.val == null)
{
return result;
}
Queue<TreeNode> queue = new Queue<TreeNode>();
queue.Enqueue(root);
while (queue.Any())
{
TreeNode p = queue.Dequeue();
result.Add(p.val);
if (p.left != null)
{
queue.Enqueue(p.left);
}
if (p.right != null)
{
queue.Enqueue(p.right);
}
}
return result;
}
常见题目
给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
public IList<string> BinaryTreePaths_DFS(TreeNode root)
{
StringBuilder path = new StringBuilder();
List<string> paths = new List<string>();
DFS(root, path, paths);
return paths;
}
void DFS(TreeNode? p, StringBuilder path, ICollection<string> paths)
{
if (p?.val == null)
{
return;
}
path.Append(p.val);
if (p.left?.val == null && p.right?.val == null)
{
paths.Add(path.ToString());
}
else
{
path.Append("->");
DFS(p.left, new StringBuilder(path.ToString()), paths);
DFS(p.right, new StringBuilder(path.ToString()), paths);
}
}
二叉树分治
先分别处理局部,再合并结果
适用场景
快速排序
归并排序
二叉树相关问题
分治法模板
递归返回条件
分段处理
合并结果
伪代码如下
public ResultType Traversal(TreeNode root) {
// null or leaf
if (root == null) {
// do something and return
}
// Divide
ResultType left = Traversal(root.Left)
ResultType right = Traversal(root.Right)
// Conquer
ResultType result = Merge from left and right
return result
}
典型示例
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
public bool IsValidBST(TreeNode root)
{
return IsValidBST_DivideAndConquer(root, long.MinValue, long.MaxValue);
}
bool IsValidBST_DivideAndConquer(TreeNode? p, long? min, long? max)
{
if (p?.val == null)
{
return true;
}
// 返回条件
if (p.val <= min || max <= p.val)
{
return false;
}
// 分治(Divide)
var left = IsValidBST_DivideAndConquer(p.left, min, p.val);
var right = IsValidBST_DivideAndConquer(p.right, p.val, max);
// 合并结果(Conquer)
return left && right;
}
常见题目
二叉树的的最大深度
给定一个二叉树 root ,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
DFS递归解法
public int MaxDepth_DFS(TreeNode? root) {
if (root?.val == null) {
return 0;
}
return Math.Max(MaxDepth_DFS(root.left), MaxDepth_DFS(root.right)) + 1;
}
BFS队列解法
public int MaxDepth_BFS(TreeNode? root) {
if (root?.val == null) {
return 0;
}
int depth = 0;
Queue<TreeNode> queue = new Queue<TreeNode>();
queue.Enqueue(root);
while (queue.Count > 0) {
depth++;
int size = queue.Count;
for (int i = 0; i < size; i++) {
TreeNode node = queue.Dequeue();
if (node.left != null) {
queue.Enqueue(node.left);
}
if (node.right != null) {
queue.Enqueue(node.right);
}
}
}
return depth;
}