最大深度
//先序遍历
//因为前面说了,前序位置是进入一个节点的时候,后序位置是离开一个节点的时候,depth 记录当前递归到的节点深度
class Solution {
int depth=0;
int max=0;
public int maxDepth(TreeNode root) {
traverse(root);
return max;
}
public void traverse(TreeNode root){
if(root==null)
return;
depth++;
if(root.left==null&&root.right==null){
max=Math.max(max,depth);
}
traverse(root.left);
traverse(root.right);
depth--;
}
}
//法二 通过子树的最大深度
int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
// 利用定义,计算左右子树的最大深度
int leftMax = maxDepth(root.left);
int rightMax = maxDepth(root.right);
// 整棵树的最大深度等于左右子树的最大深度取最大值,
// 然后再加上根节点自己
int res = Math.max(leftMax, rightMax) + 1;
return res;
}
层序遍历
dfs
class Solution {
List<List<Integer>> list=new ArrayList();
public List<List<Integer>> levelOrder(TreeNode root) {
dfs(root,0);
return list;
}
public void dfs(TreeNode root,int depth){
if(root==null){
return;
}
if(list.size()<=depth){
List<Integer> alist=new ArrayList();
list.add(alist);
}
list.get(depth).add(root.val);
depth+=1;
ceng(root.left,depth);
ceng(root.right,depth);
}
}
bfs
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();
if(root==null) return ans;
Queue<TreeNode> queue=new LinkedList();
queue.offer(root);
while(!queue.isEmpty()){
List<Integer> list=new ArrayList();
int size=queue.size();//该层有多少个节点
while(size!=0){
TreeNode tmp=queue.poll();
list.add(tmp.val);
if(tmp.left!=null){
queue.offer(tmp.left);
}
if(tmp.right!=null){
queue.offer(tmp.right);
}
size--;
}
ans.add(list);
}
return ans;
}
}
二叉树的最近公共祖先
class Solution {
//既在左子树找p和q,又在右子树找p和q。 只要找到p或q的其中一个就可以返回
//如果left和right都不为空,说明左右子树各找到p和q当中的一个,那么p和q在root的两侧。
//如果left不为空,说明p,q在左子树。 如果right不为空,说明p,q在右子树。
//left和right都为空,说明找不到。
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null){//访问到叶子节点
return null;
}
if(root==p||root==q){//访问到一个即可返回
return root;
}
//遍历左节点
TreeNode left=lowestCommonAncestor(root.left,p,q);
//遍历右节点
TreeNode right=lowestCommonAncestor(root.right,p,q);
if(left!=null&&right!=null){//p和q在root的两侧
return root;
}
if(left==null){//说明p和q在右子树里面
return right;
}
if(right==null){//说明p和q在左子树里面
return left;
}
return null; //说明找不到
}
}
二叉树的最大路径和
class Solution {
private int ret = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
/**
对于任意一个节点, 如果最大和路径包含该节点, 那么只可能是两种情况:
1. 其左右子树中所构成的和路径值较大的那个加上该节点的值后向父节点回溯构成最大路径
2. 左右子树都在最大路径中, 加上该节点的值构成了最终的最大路径
**/
getMax(root);
return ret;
}
//返回以root为根节点的二叉树的左右子树中和最大的那一条路径
private int getMax(TreeNode r) {
if(r == null) return 0;
int left = Math.max(0, getMax(r.left)); // 如果子树路径和为负则应当置0表示最大路径不包含子树
int right = Math.max(0, getMax(r.right));
ret = Math.max(ret, r.val + left + right); // 判断在该节点包含左右子树的路径和是否大于当前最大路径和
return Math.max(left, right) + r.val;
}
}
二叉树的右视图
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
getRightNode(root,res,0);
return res;
}
//每层取最右边的元素
private void getRightNode(TreeNode root,List<Integer> res,int depth){
if(root == null) return;
if(depth == res.size()){
res.add(root.val);
}
//优先遍历右边
getRightNode(root.right,res,depth+1);
getRightNode(root.left,res,depth+1);
}
}
652. 寻找重复的子树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//hashmap保存每个序列出现的次数,当当前出现的序列已出现时说明重复了,就加入结果集
HashMap<String, Integer> map = new HashMap<>();
List<TreeNode> res = new ArrayList<>();
public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
preConstruct(root);
return res;
}
//通过后后序遍历序列化
public String preConstruct(TreeNode root){
//对于空节点,返回“#”
if(root == null){
return "#";
}
//将左右子树序列化为字符串
String left = preConstruct(root.left);
String right = preConstruct(root.right);
//左+右+自己即为当前节点的序列化
String str = left + "," + right + "," + root.val;
int count = map.getOrDefault(str,0)+1;
if(count == 2){
res.add(root);
}
map.put(str,count);
return str;
}
}