九章系列(2)——二叉树&分治(DFS&BFS)

这篇博客详细介绍了二叉树的深度优先搜索(DFS)和广度优先搜索(BFS)遍历方法,包括前序、中序、后序遍历。同时强调了在二叉树问题中分治策略的重要性,并提供了多个二叉树相关问题的分治解法,如二叉树的最大深度、判断平衡二叉树、最近公共祖先等。还分享了不同类型的DFS模板,包括递归和非递归(借助栈)方式,并给出了相关LeetCode题目链接供读者实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Outline

1.Binary Tree DFS Traversal
  • preorder / inorder / postorder
  • Divide & Conquer
  • DFS Template
2.Binary Tree BFS Traversal
  • BFS template
3. Binary Search Tree
  • validate, insert, delete

note:二叉树问题,首选分治(天然分治场景,解决80%问题);

1.1 DFS模板
模板一:
递归;

public class Solution {
    public void traverse(TreeNode root) {
        if (root == null) {
            return;
        }
        // do something with root
        traverse(root.left);
        // do something with root
        traverse(root.right);
        // do something with root
    }
}

模板二:
分治思想;

Tempate 2: Divide & Conquer

public class Solution {
    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;
    }
}

练习题:
T-1 二叉树前序遍历
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

解法一:递归

public class Solution {
    public ArrayList<Integer> preorderTraversal(TreeNode root) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        traverse(root, result);
        return result;
    }
    // 把root为跟的preorder加入result里面
    private void traverse(TreeNode root, ArrayList<Integer> result) {
        if (root == null) {
            return;
        }

        result.add(root.val);
        traverse(root.left, result);
        traverse(root.right, result);
    }
}

解法二:借助栈,遍历实现;
本质上跟递归一样,区别是递归使用的是系统栈;

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        Stack<TreeNode> st = new Stack<TreeNode>();
        TreeNode node = root;
        while(node!=null||st.size()>0) {
        	while(node!=null) {
        		res.add(node.val);
        		st.push(node);
        		node=node.left;
        	}
        	if(!st.empty()) {
        		node=st.pop();
        		node=node.right;
        	}
        }
        return res;
    }
}

解法三:
分治;

public class Solution {
    public ArrayList<Integer> preorderTraversal(TreeNode root) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        // null or leaf
        if (root == null) {
            return result;
        }

        // Divide
        ArrayList<Integer> left = preorderTraversal(root.left);
        ArrayList<Integer> right = preorderTraversal(root.right);

        // Conquer
        result.add(root.val);
        result.addAll(left);
        result.addAll(right);
        return result;
    }
}

T-2 二叉搜索树的迭代器
https://leetcode-cn.com/problems/binary-search-tree-iterator/

T-3 二叉树的最大深度
https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/

解法一:
分治法:

public class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }

        int left = maxDepth(root.left);
        int right = maxDepth(root.right);
        return Math.max(left, right) + 1;
    }
}

解法二:遍历

    public int maxDepth(TreeNode root) {
        if(root==null)
            return 0;
    Queue<TreeNode> qu = new LinkedList<TreeNode>();
    qu.offer(root);
    int depth=0;
    while(qu.size()>0) {
    	int size=qu.size();
    	depth++;
    	while(size-->0) {
    		TreeNode node = qu.poll();
    		if(node.left!=null)
    			qu.offer(node.left);
    		if(node.right!=null)
    			qu.offer(node.right);
    	}
    }
    return depth;
    }

T-4 判断是否是平衡二叉树
https://leetcode-cn.com/problems/balanced-binary-tree/

技巧:
使用-1代表不平衡;
分治法;

public class Solution {
    public boolean isBalanced(TreeNode root) {
        return maxDepth(root) != -1;
    }

    private int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }

        int left = maxDepth(root.left);
        int right = maxDepth(root.right);
        if (left == -1 || right == -1 || Math.abs(left-right) > 1) {
            return -1;
        }
        return Math.max(left, right) + 1;
    }
}

T-5 二叉树的最近公共祖先
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/

分治法:

public class Solution {
    // 在root为根的二叉树中找A,B的LCA:
    // 如果找到了就返回这个LCA
    // 如果只碰到A,就返回A
    // 如果只碰到B,就返回B
    // 如果都没有,就返回null
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode node1, TreeNode node2) {
        if (root == null || root == node1 || root == node2) {
            return root;
        }
        
        // Divide
        TreeNode left = lowestCommonAncestor(root.left, node1, node2);
        TreeNode right = lowestCommonAncestor(root.right, node1, node2);
        
        // Conquer
        if (left != null && right != null) {
            return root;
        } 
        if (left != null) {
            return left;
        }
        if (right != null) {
            return right;
        }
        return null;
    }
}

T-6 二叉树中的最大路径和
https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/

public class Solution {
    private class ResultType {
        // singlePath: 从root往下走到任意点的最大路径,这条路径可以不包含任何点
        // maxPath: 从树中任意到任意点的最大路径,这条路径至少包含一个点
        int singlePath, maxPath; 
        ResultType(int singlePath, int maxPath) {
            this.singlePath = singlePath;
            this.maxPath = maxPath;
        }
    }

    private ResultType helper(TreeNode root) {
        if (root == null) {
            return new ResultType(0, Integer.MIN_VALUE);
        }
        // Divide
        ResultType left = helper(root.left);
        ResultType right = helper(root.right);

        // Conquer
        int singlePath = Math.max(left.singlePath, right.singlePath) + root.val;
        singlePath = Math.max(singlePath, 0);

        int maxPath = Math.max(left.maxPath, right.maxPath);
        maxPath = Math.max(maxPath, left.singlePath + right.singlePath + root.val);

        return new ResultType(singlePath, maxPath);
    }

    public int maxPathSum(TreeNode root) {
        ResultType result = helper(root);
        return result.maxPath;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值