二叉树相关LC题代码整理(41题)

深度优先遍历DFS

在这里插入图片描述

144.二叉树的前序遍历

145.二叉树的后序遍历

94. 二叉树的中序遍历

方法一:递归

class Solution {
	//前序
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<Integer>();
        preorder(root,res);
        return res;
    }
    public void preorder(TreeNode root,List<Integer> res){
        if(root==null) return;
        res.add(root.val);//中
        preorder(root.left,res);
        preorder(root.right,res);
    }
    //后序
    public List<Integer> postorderTraversal(TreeNode root) {
         List<Integer> res=new ArrayList<Integer>();
         postorder(root,res);
         return res;
     }
    public void postorder(TreeNode root,List<Integer> res){
         if(root==null)  return;
         postorder(root.left,res);
         postorder(root.right,res);
         res.add(root.val);
     }
     //中序
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        inorder(res,root);
        return res;
    }
    public void inorder(List<Integer> res,  TreeNode root){
        if(root == null) return;
            inorder(res,root.left);
            res.add(root.val);
            inorder(res,root.right);
    }
}

方法二:迭代(即用栈来模拟递归调用的过程)

class Solution {
    //前序迭代
    public List<Integer> preorderTraversal(TreeNode root){
        List<Integer> res=new ArrayList<Integer>();
        Stack<TreeNode> stack=new Stack<TreeNode>();
        if(root==null) return new ArrayList<Integer>();
        stack.push(root);
        while(stack.size()>0){
            TreeNode node=stack.pop();
            res.add(node.val);
            if(node.right!=null) stack.push(node.right);
            if(node.left!=null) stack.push(node.left);//栈先进后出 故先放右节点
        }
        return res;
    }
    //后序迭代:与前序差不多
    public List<Integer> postorderTraversal(TreeNode root){
        List<Integer> res=new ArrayList<Integer>();
        Stack<TreeNode> stack=new Stack<TreeNode>();
        if(root==null) return new  ArrayList<>();
        stack.push(root);
        while(stack.size()>0){
            TreeNode node =stack.pop();
            res.add(node.val);
            if(node.left!=null) stack.push(node.left);
            if(node.right!=null) stack.push(node.right);
            
        }
        Collections.reverse(res);
        return res;
    }
    //中序迭代:与前序遍历不同,需要遍历到最左节点再开始出栈,然后转向右边继续
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new  ArrayList<Integer>();
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while(root!=null||stack.size()>0){
            if(root!=null){
                stack.push(root);
                root=root.left;//一直向左找
            }else{
                TreeNode node=stack.pop();
                res.add(node.val);
                root=node.right;
            }  
        } 
        return res;
    }

}

方法三:迭代法 前中后序统一格式框架:添加空节点!
为了解决中序遍历时访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况不,在每次要处理的节点放入栈之后,紧接着放入一个空节点作为标记,最后出栈的时候遇到空节点就知道,它之后是要处理的节点。

    public List<Integer> Traversal(TreeNode root) {
        List<Integer> res = new  ArrayList<Integer>();
        Stack<TreeNode> stack = new Stack<TreeNode>();
        if(root!=null) stack.push(root);
        while(stack.size()>0){
            TreeNode node=stack.peek();
            if(node!=null) {
                stack.pop();
                
                //1、前序遍历的入栈顺序为 右--左--中
                //2、后序遍历的入栈顺序为 中--右--左
                //3、中序遍历的入栈顺序为 右--中--左
                
            }else{//遇到空节点时弹出下一节点
                stack.pop();
                node=stack.pop();
                res.add(node.val);
            }
        }
        return res;
    }

1、前序遍历的入栈顺序为 右–左--中

				if(node.right!=null) stack.push(node.right);//右
                if(node.left!=null) stack.push(node.left);//左   
                stack.push(node);//中
                stack.push(null);//添加空节点做标记

2、后序遍历的入栈顺序为 中–右--左

				stack.push(node);//中
                stack.push(null);
                if(node.right!=null) stack.push(node.right);//右
                if(node.left!=null) stack.push(node.left);

3、中序遍历的入栈顺序为 右–中--左

				if(node.right!=null) stack.push(node.right);//右
                stack.push(node);//中
                stack.push(null);//添加空节点做标记
                if(node.left!=null) stack.push(node.left);//左   

589.N叉树的前序遍历

class Solution {
    //迭代框架版
    public List<Integer> preorder(Node root) {
        List<Integer> res=new ArrayList<Integer>();
        Stack<Node> stack=new Stack<Node>();
        if(root!=null) stack.push(root);
        while(stack.size()>0){
            Node node=stack.peek();
            if(node!=null){
                stack.pop();
                Collections.reverse(node.children);//入栈顺序要反过来
                for(Node childNode:node.children){
                    stack.push(childNode);
                }
                stack.push(node);
                stack.push(null);
            }else{
                stack.pop();
                node=stack.pop();
                res.add(node.val);
            }
        }
        return res;
    }
    public List<Integer> preorder(Node root) {
        LinkedList<Node> stack = new LinkedList<>();
        LinkedList<Integer> output = new LinkedList<>();
        if (root == null) {
            return output;
        }
        stack.add(root);
        while (!stack.isEmpty()) {
            Node node = stack.pollLast();
            output.add(node.val);
            Collections.reverse(node.children);
            for (Node item : node.children) {
                stack.add(item);
            }
        }
        return output;
    }
}

590.N叉树的后序遍历

class Solution {
    //迭代
    public List<Integer> postorder(Node root) {
        List<Integer> res=new ArrayList<Integer>();
        Stack<Node> stack=new Stack<Node>();
        if(root!=null) stack.push(root);
        while(stack.size()>0){
            Node node=stack.peek();
            if(node!=null){
                stack.pop();
                for(Node childNode:node.children){
                    stack.push(childNode);
                }
                stack.push(node);
                stack.push(null);
            }else{
                stack.pop();
                node=stack.pop();
                res.add(node.val);
            } 
        }
        Collections.reverse(res);
        return res;
    }
    
}

257. 二叉树的所有路径

给定一个二叉树,返回所有从根节点到叶子节点的路径。

class Solution {
    //递归 深度优先遍历
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> paths=new ArrayList<String>();
        getBinaryPaths(root,"",paths);
        return paths;
        
    }
    public void getBinaryPaths(TreeNode root,String path,List<String> paths){
        if(root!=null){
            StringBuffer pathSB=new StringBuffer(path);
            pathSB.append(Integer.toString(root.val));
            if(root.left==null&&root.right==null){
                paths.add(pathSB.toString());
            }else{
                pathSB.append("->");
                getBinaryPaths(root.left,pathSB.toString(),paths);
                getBinaryPaths(root.right,pathSB.toString(),paths);
            }
        }
    }
}

广度优先遍历BFS

在这里插入图片描述

102.二叉树的层序遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res= new ArrayList<List<Integer>>();
        LinkedList<TreeNode> que=new LinkedList<TreeNode>();
        if(root!=null) que.add(root);
        while(que.size()>0){
            int size=que.size();//队列大小相当于每层节点个数
            ArrayList<Integer> temp=new ArrayList<Integer>();//每层节点放入一个list集合
            for(int i=0;i<size;i++){
                TreeNode node=que.remove();
                temp.add(node.val);
                if(node.left!=null) que.add(node.left);
                if(node.right!=null) que.add(node.right);
            }
            res.add(temp);
        }
        return res;
    }
}

429.N叉树的层次遍历

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> res=new ArrayList<List<Integer>>();
        LinkedList<Node> que=new LinkedList<Node>();
        if(root!=null) que.add(root);
        while(que.size()>0){
            int size=que.size();
            ArrayList<Integer> temp=new ArrayList<Integer>();
            for(int i=0;i<size;i++){
                Node node=que.remove();
                temp.add(node.val);
                for(Node childNode:node.children){//把每一层孩子节点加入集合
                    que.add(childNode);
                }
            }
            res.add(temp);
        }
        return res;
    }
}

107. 二叉树的层次遍历 II

给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
翻转102的结果集即可。

class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> res=new ArrayList<List<Integer>>();
        LinkedList<TreeNode> que=new LinkedList<TreeNode>();
        if(root!=null) que.add(root);
        while(que.size()>0){
            int size=que.size();
            ArrayList<Integer> temp=new ArrayList<Integer>();
            for(int i=0;i<size;i++){
                TreeNode node=que.remove();
                temp.add(node.val);
                if(node.left!=null) que.add(node.left);
                if(node.right!=null) que.add(node.right);
            } 
            res.add(temp);
        }
        Collections.reverse(res);//翻转list集合
        return res;
    }
}

104. 二叉树的最大深度==剑指55

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
此题因为是求最大深度,所以可以用层次遍历统计一共多少层。

class Solution {
    public int maxDepth(TreeNode root) {
        LinkedList<TreeNode> que=new LinkedList<TreeNode>();
        if(root!=null) que.add(root);
        int depth=0;
        while(que.size()>0){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode node=que.remove();
                //res.add(node.val);
                if(node.left!=null) que.add(node.left);
                if(node.right!=null) que.add(node.right);
            }
            depth++;//层次遍历 每遍历一次记录一次
        }
        return depth;
    }
    // //递归
    // public int maxDepth(TreeNode root){
    //     if(root==null) return 0;
    //     int leftHeight=maxDepth(root.left);
    //     int rightHeight=maxDepth(root.right);
    //     return Math.max(leftHeight,rightHeight)+1;
    // }
}

559. N 叉树的最大深度

class Solution {
    //递归
    // public int maxDepth(Node root) {
    //     if(root==null) return 0;
    //     int depth=0;
    //     for(Node child:root.children){
    //         depth=Math.max(depth,maxDepth(child));
    //     }
    //     return depth+1;
    // }
    //迭代
    public int maxDepth(Node root){
        LinkedList<Node> que=new LinkedList<Node>();
        if(root!=null) que.add(root);
        int depth=0;
        while(que.size()>0){
            int size=que.size();
            depth++;
            for(int i=0;i<size;i++){
                Node node=que.remove();
                for(Node child:node.children){
                    que.add(child);
                }
            }
        }
        return depth;
    }
}

111. 二叉树的最小深度

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

class Solution {
    // 递归
    // public int minDepth(TreeNode root) {
    //     if(root==null) return 0;
    //     int leftHeight=minDepth(root.left);
    //     int rightHeight=minDepth(root.right);
    //     return leftHeight==0||rightHeight==0?Math.max(leftHeight,rightHeight)+1:Math.min(leftHeight,rightHeight)+1;
    // }
    public int minDepth(TreeNode root){
        LinkedList<TreeNode> que=new LinkedList<TreeNode>();
        if(root!=null) que.add(root);
        int depth=0;
        while(que.size()>0){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode node=que.remove();
                if(node.left==null&&node.right==null){
                    return depth+1;//若遇到了叶节点 则直接返回层数+1(为什么加一 画图模拟下即可) LC上默认根节点深度为1
                }
                if(node.left!=null) que.add(node.left);
                if(node.right!=null) que.add(node.right);
            }
            depth++;
        }
        return depth;
    }
}

199. 二叉树的右视图

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res=new ArrayList<Integer>();
        LinkedList<TreeNode> que=new LinkedList<TreeNode>();
        if(root!=null) que.add(root);
        while(que.size()>0){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode node=que.remove();
                if(i==size-1) res.add(node.val);//只保存每一层最右节点
                if(node.left!=null) que.add(node.left);
                if(node.right!=null) que.add(node.right);
            }
        }
        return res;
    }
}

637. 二叉树的层平均值

给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。

class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> res=new ArrayList<Double>();
        LinkedList<TreeNode> que=new LinkedList<TreeNode>();
        if(root!=null) que.add(root);
        while(que.size()>0){
            int size=que.size();
            double sum=0;//每层节点的和
            for(int i=0;i<size;i++){
                TreeNode node=que.remove();
                sum+=node.val;
                if(node.left!=null) que.add(node.left);
                if(node.right!=null) que.add(node.right);
            }
            res.add(sum/size);//每层节点的平均值加入结果集
        }
        return res;
    }
}

116. 填充每个节点的下一个右侧节点指针

给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。

class Solution {
    public Node connect(Node root) {
       LinkedList<Node> que=new LinkedList<Node>();
       if(root!=null) que.add(root);
       while(que.size()>0){
           int size=que.size();
           Node node=null;
           Node nodePre=null;
           for(int i=0;i<size;i++){
               if(i==0){
                   nodePre=que.remove();
                   node=nodePre;//取出每一层的第一个节点
               }else{
                   node=que.remove();
                   nodePre.next=node;//前一节点的next指向当前节点
                   nodePre=nodePre.next;
               }
               if(node.left!=null) que.add(node.left);
               if(node.right!=null) que.add(node.right);
           }
           nodePre.next=null;//最后一个节点指向空
       }
       return root;
    }
}

117. 填充每个节点的下一个右侧节点指针 II

与116不同的是:没规定是完美二叉树 代码相同

515. 在每个树行中找最大值

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> res=new ArrayList<Integer>();
        LinkedList<TreeNode> que=new LinkedList<TreeNode>();
        if(root!=null) que.add(root);
        while(que.size()>0){
            int size=que.size();
            int maxVal=Integer.MIN_VALUE;
            for(int i=0;i<size;i++){
                TreeNode node=que.remove();
                maxVal=node.val>maxVal?node.val:maxVal;//每层找最大值即可
                if(node.left!=null) que.add(node.left);
                if(node.right!=null) que.add(node.right);
            }
            res.add(maxVal);
        }
        return res;
    }
}

226. 翻转二叉树==剑指27题

class Solution {
    //递归
    public TreeNode invertTree(TreeNode root) {
        if(root==null) return root;//递归终止条件
        TreeNode temp=root.right;
        root.right=root.left;
        root.left=temp;//前序遍历  先处理根节点 交换左右
        invertTree(root.left);//左
        invertTree(root.right);//右    
        return root;
    }
    //迭代
    public TreeNode invertTree(TreeNode root){
        Stack<TreeNode> stack=new Stack<TreeNode>();
        if(root!=null) stack.push(root);
        while(stack.size()>0){
            TreeNode node=stack.pop();
            TreeNode temp=node.left;
            node.left=node.right;
            node.right=temp;        //交换左右          中
            if(node.right!=null) stack.push(node.right);//右
            if(node.left!=null) stack.push(node.left);//左
        }
        return root;
    }
    //迭代 统一写法
    public TreeNode invertTree(TreeNode root){
        Stack<TreeNode> stack=new Stack<TreeNode>();
        if(root!=null) stack.push(root);
        while(stack.size()>0){
            TreeNode node=stack.peek();
            if(node!=null){
                stack.pop();
                if(node.right!=null) stack.push(node.right);//右
                if(node.left!=null) stack.push(node.left);//左
                stack.push(node);//中
                stack.push(null);
            }else{
                stack.pop();
                node=stack.pop();
                TreeNode temp=node.left;
                node.left=node.right;
                node.right=temp;
            }
        }
        return root;
    }
    //层序遍历
    public TreeNode invertTree(TreeNode root){
        LinkedList<TreeNode> que=new LinkedList<TreeNode>();
        if(root!=null) que.add(root);
        while(que.size()>0){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode node=que.remove();
                TreeNode temp=node.left;
                node.left=node.right;
                node.right=temp;
                if(node.left!=null) que.push(node.left);
                if(node.right!=null) que.push(node.right);
            }
        }
        return root;
    }
}

222. 完全二叉树的节点个数

class Solution {
    //递归
    // public int countNodes(TreeNode root) {
    //     if(root==null) return 0;
    //     int leftCount=countNodes(root.left);
    //     int rightCount=countNodes(root.right);
    //     int count=leftCount+rightCount+1;
    //     return count;
    // }
    //迭代 层序遍历统计遍历过得节点数
    public int countNodes(TreeNode root){
        LinkedList<TreeNode> que=new LinkedList<TreeNode>();
        if(root!=null) que.add(root);
        int depth=0;
        while(que.size()>0){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode node=que.remove();
                depth++;
                if(node.left!=null) que.add(node.left);
                if(node.right!=null) que.add(node.right);
            }
        }
        return depth;
    }
}

110. 平衡二叉树==剑指55题

class Solution {
    //递归
    public int getDepth(TreeNode node){
        if(node==null) return 0;
        int leftheight=getDepth(node.left);
        if(leftheight==-1) return -1;
        int rightheight=getDepth(node.right);
        if(rightheight==-1) return -1;
        int height=Math.abs(leftheight-rightheight)>1?-1:1+Math.max(leftheight,rightheight);
        return height;
    }
    public boolean isBalanced(TreeNode root) {
        int res=getDepth(root);
        if(res==-1) return false;
        else return true;
    }
    
}

100. 相同的树

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        return compare(p,q);
    }
    public boolean compare(TreeNode tree1,TreeNode tree2){
        if(tree1==null&&tree2==null) return true;
        else if(tree1!=null&&tree2==null) return false;
        else if(tree1==null&&tree2!=null) return false;
        else if(tree1.val!=tree2.val) return false;
        // 此时就是:左右节点都不为空,且数值相同的情况
        boolean outside=compare(tree1.left,tree2.left);
        boolean inside=compare(tree1.right,tree2.right);
        boolean isSame=outside&&inside;
        return isSame;
    }
}

101. 对称二叉树==剑指28题

class Solution {
    //递归
    // public boolean isSymmetric(TreeNode root) {
    //     if(root==null) return true;
    //     return compare(root.left,root.right);
    // }
    // public boolean compare(TreeNode left,TreeNode right){
    //     if(left==null&&right!=null) return false;
    //     else if(left!=null&&right==null) return false;
    //     else if(left==null&&right==null) return true;
    //     else if(left.val!=right.val) return false;
    //     boolean outside=compare(left.left,right.right);//外侧比较的是左节点的左孩子和右节点的右孩子
    //     boolean inside=compare(left.right,right.left);//内侧比较的是左节点的右孩子和右节点的左孩子
    //     boolean isSame=outside&&inside;
    //     return isSame;
    // }
    //迭代
    public boolean isSymmetric(TreeNode root){
        if(root==null) return true;
        Stack<TreeNode> st=new Stack<TreeNode>();//把要比较的节点放入一个容器(队列、数组都可以)两两比较
        st.push(root.left);
        st.push(root.right);
        while(st.size()>0){
            TreeNode leftNode=st.pop();
            TreeNode rightNode=st.pop();
            if(leftNode==null&&rightNode==null) continue;
            if((leftNode==null||rightNode==null||leftNode.val!=rightNode.val)) return false;
            st.push(leftNode.left);
            st.push(rightNode.right);
            st.push(leftNode.right);
            st.push(rightNode.left);
        }
        return true;
    }
}

513. 找树左下角的值

class Solution {
    //BFS
    // public int findBottomLeftValue(TreeNode root) {
    //     int res = 0;
    //     LinkedList<TreeNode> que = new LinkedList<>();
    //     if(root!=null) que.add(root);
    //     while (que.size()>0)
    //     {
    //         int size = que.size();
    //         for (int i = 0; i < size; i++)
    //         {
    //             TreeNode node = que.remove();
    //             if (i == 0) res = node.val;//记录最左节点值
    //             if (node.left != null) que.add(node.left);
    //             if (node.right != null) que.add(node.right);
    //         }
    //     }
    //     return res;
    // }
    //BFS改进:改为从上到下,从右到左遍历,则遍历的最后一个节点肯定是最后一行最左边的值
    public int findBottomLeftValue(TreeNode root) {
        int res=0;
        LinkedList<TreeNode> que=new LinkedList<TreeNode>();
        if(root!=null) que.add(root);
        while(que.size()>0){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode node=que.remove();
                res=node.val;
                if(node.right!=null) que.add(node.right);
                if(node.left!=null) que.add(node.left);
            }
        }
        return res;
    }

}

404. 左叶子之和

class Solution {
    //递归
    // public int sumOfLeftLeaves(TreeNode root) {
    //     int sum=0;
    //     if(root==null) return 0;
    //     if(root.left!=null&&root.left.left==null&&root.left.right==null){
    //         sum=root.left.val;
    //     }
    //     return sum+sumOfLeftLeaves(root.left)+sumOfLeftLeaves(root.right);
    // }
    //迭代
    public int sumOfLeftLeaves(TreeNode root){
        Stack<TreeNode> stack=new Stack<TreeNode>();
        int sum=0;
        if(root!=null) stack.push(root);
        while(stack.size()>0){
            TreeNode node=stack.pop();
            if(node.left!=null&&node.left.left==null&&node.left.right==null){
                sum+=node.left.val;
            }
            if(node.left!=null) stack.push(node.left);
            if(node.right!=null) stack.push(node.right);
        }
        return sum;
    }
}

572. 另一个树的子树

class Solution {
    public boolean isSubtree(TreeNode s, TreeNode t) {
        if(s==null) return false;
        else if(s.val==t.val&&isSame(s,t)){
            return true;
        }else return isSubtree(s.left,t)||isSubtree(s.right,t);
    }
    public boolean isSame(TreeNode tree1,TreeNode tree2){
        if(tree1==null&&tree2==null) return true;
        else if(tree1!=null&&tree2==null) return false;
        else if(tree1==null&&tree2!=null) return false;
        else if(tree1.val!=tree2.val) return false;
        // 此时就是:左右节点都不为空,且数值相同的情况
        boolean outside=isSame(tree1.left,tree2.left);
        boolean inside=isSame(tree1.right,tree2.right);
        boolean res=outside&&inside;
        return res;
    }
}

112. 路径总和

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
        if(root==null) return false;
        return traversal(root,sum-root.val);
    
    }
    public boolean traversal(TreeNode cur,int count){
        if (cur.left==null&&cur.right==null&&count == 0) return true; // 遇到叶子节点,并且计数为0
        if (cur.left==null&&cur.right==null) return false; // 遇到叶子节点直接返回
        if (cur.left!=null) { // 左
            count -= cur.left.val; // 递归,处理节点;
            if (traversal(cur.left, count)) return true;
            count += cur.left.val; // 回溯,撤销处理结果
        }
        if (cur.right!=null) { // 右
            count -= cur.right.val; // 递归,处理节点;
            if (traversal(cur.right, count)) return true;
            count += cur.right.val; // 回溯,撤销处理结果
        }
        return false;
    }
}

113. 路径总和 II==剑指34

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> res=new ArrayList();
        List<Integer> list=new ArrayList();
        backTrack(root,sum,list,res);
        return res;
    }
   public void backTrack(TreeNode node,int sum,List<Integer> list,List<List<Integer>> res){
       if(node==null) return;
       list.add(node.val);
       if(node.left==null&&node.right==null&&sum-node.val==0){//找到叶子节点并且和为sum
            res.add(new ArrayList(list));//添加路径
            list.remove(list.size()-1);
            return;
       }
       backTrack(node.left,sum-node.val,list,res);
       backTrack(node.right,sum-node.val,list,res);
       list.remove(list.size()-1);
   }
}

106. 从中序与后序遍历序列构造二叉树

class Solution {
    HashMap<Integer,Integer> inorderMap=new HashMap<>();
    int[] post;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        for(int i=0;i<inorder.length;i++){
            inorderMap.put(inorder[i],i);
        }
        post=postorder;
        TreeNode root=buildTree(0,inorder.length-1,0,postorder.length-1);
        return root;
    }
    public TreeNode buildTree(int iStart,int iEnd,int pStart,int pEnd){
        if(iEnd<iStart||pEnd<pStart) return null;
        int root=post[pEnd];
        int rootIndex=inorderMap.get(root);
        TreeNode node=new TreeNode(root);//创建该节点
        node.left=buildTree(iStart,rootIndex-1,pStart,pStart+rootIndex-iStart-1);//左递归
        node.right=buildTree(rootIndex+1,iEnd,pStart+rootIndex-iStart,pEnd-1);//右递归
        return node;
    }
}

105. 从前序与中序遍历序列构造二叉树

class Solution {
    HashMap<Integer, Integer> inorderMap = new HashMap<>();
    int[] pre;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        for (int i = 0; i < inorder.length; i++) {
            inorderMap.put(inorder[i], i);
        }
        pre=preorder;
        return buildTree( 0, preorder.length, 0, inorder.length);
    }

    private TreeNode buildTree(int p_start, int p_end, int i_start, int i_end) {
        if (p_start == p_end) {
            return null;
        }
        int root_val = pre[p_start];
        TreeNode root = new TreeNode(root_val); 
        int i_root_index = inorderMap.get(root_val);
        int leftNum = i_root_index - i_start;
        root.left = buildTree( p_start + 1, p_start + leftNum + 1, i_start, i_root_index);
        root.right = buildTree( p_start + leftNum + 1, p_end, i_root_index + 1, i_end);
        return root;
    }
}

654. 最大二叉树

给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:

二叉树的根是数组中的最大元素。
左子树是通过数组中最大值左边部分构造出的最大二叉树。
右子树是通过数组中最大值右边部分构造出的最大二叉树。

通过给定的数组构建最大二叉树,并且输出这个树的根节点。

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return buildTree(nums,0,nums.length);
    }
    public TreeNode buildTree(int[] nums,int left,int right){
        if(left>=right) return null;
        int maxValIndex=left;
        for(int i=left+1;i<right;i++){
            if(nums[i]>nums[maxValIndex]){
                maxValIndex=i;
            }
        }
        int maxVal=nums[maxValIndex];//找到最大值作为分割点
        TreeNode root=new TreeNode(maxVal);
        root.left=buildTree(nums,left,maxValIndex);
        root.right=buildTree(nums,maxValIndex+1,right);
        return root;
    }
}

617. 合并二叉树

合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。

class Solution {
    //递归
    // public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
    //     if(t1==null) return t2;
    //     if(t2==null) return t1;
    //     TreeNode root=new TreeNode(0);
    //     root.val=t1.val+t2.val;
    //     root.left=mergeTrees(t1.left,t2.left);
    //     root.right=mergeTrees(t1.right,t2.right);
    //     return root;
    // }
    //使用队列模拟类似层序遍历
    public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
        LinkedList<TreeNode> que=new LinkedList<>();
        if(t1==null) return t2;
        if(t2==null) return t1;
        que.add(t1);
        que.add(t2);
        while(que.size()>0){
            TreeNode node1=que.peek();
            que.pop();
            TreeNode node2=que.peek();
            que.pop();
            node1.val+=node2.val;
            if(node1.left!=null&&node2.left!=null){
                que.add(node1.left);
                que.add(node2.left);
            }
            if(node1.right!=null&&node2.right!=null){
                que.add(node1.right);
                que.add(node2.right);
            }
            if(node1.left==null&&node2.left!=null){
                node1.left=node2.left;
            }
            if(node1.right==null&&node2.right!=null){
                node1.right=node2.right;
            }
        }
        return t1;
    }
}

98. 验证二叉搜索树

class Solution {
    //递归
    TreeNode pre=null;
    public boolean isValidBST(TreeNode root) {
        return inorderDfs(root);
    }
    public boolean inorderDfs(TreeNode root){
        if(root==null) return true;//空树也是二叉搜索树
        if(inorderDfs(root.left)){
            if(pre==null){
                pre=root;
            }else if(pre.val>=root.val){
                return false;
            }else{
                pre=root;
            }
            return inorderDfs(root.right);
        }
        return false;
    }
    //迭代
    public boolean isValidBST(TreeNode root){
        if(root == null) return true;
        Integer preValue = null;
        TreeNode node = root;
        Stack<TreeNode> stack = new Stack<>();
        while(stack.size() > 0 || node != null){
            while(node != null){
                stack.push(node);
                node = node.left;
            }
            node = stack.pop();
            if(preValue == null){
                preValue = node.val;
            }else if(preValue >= node.val){
                return false;
            }
            preValue = node.val;
            node = node.right;
        }
        return true;
    }
}

530. 二叉搜索树的最小绝对差

给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。

class Solution {
    //递归
    int min=Integer.MAX_VALUE;
    TreeNode pre;
    public int getMinimumDifference(TreeNode root) {
        inorder(root);
        return min;
    }
    public void inorder(TreeNode root) {
        if(root==null) return;
        inorder(root.left);
        if(pre!=null){
            min=Math.min(min,root.val-pre.val);
        }
        pre=root;
        inorder(root.right);
    }
    //迭代
     public int getMinimumDifference(TreeNode root) {
        int min=Integer.MAX_VALUE;
        Stack<TreeNode> stack=new Stack<>();
        TreeNode node=root; 
        TreeNode pre=null;
        while (stack.size()>0||node!=null) {
            if(node!=null){
                stack.push(node);
                node=node.left;
            }else{
                node=stack.pop();
                if (pre!=null)
                min = Math.min(min,node.val-pre.val);
                pre=node;
                node=node.right;
            }
        }
        return min;
    }
}

236. 二叉树的最近公共祖先==剑指68

class Solution {
    //后序遍历 自底向上回溯
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root==p||root==q||root==null) return root;
        TreeNode left=lowestCommonAncestor(root.left,p,q);
        TreeNode right=lowestCommonAncestor(root.right,p,q);
        if(left==null) return right;
        if(right==null) return left;
        if(left==null&&right==null) return null;
        return root; //lef!=null&&right!=null
    }
}

235. 二叉搜索树的最近公共祖先==剑指68

利用bst的特性

class Solution {
    // 同236
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root==p||root==q||root==null) return root;
        TreeNode left=lowestCommonAncestor(root.left,p,q);
        TreeNode right=lowestCommonAncestor(root.right,p,q);
        if(left==null) return right;
        if(right==null) return left;
        if(left==null&&right==null) return null;
        return root; //lef!=null&&right!=null
    }
    // 利用bst的性质 迭代
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while(root!=null){
            if(root.val>p.val&&root.val>q.val){
                root=root.left;
            }else if(root.val<p.val&&root.val<q.val){
                root=root.right;
            }else return root;   
        } 
        return null;
    }
    // 递归
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root.val>p.val&&root.val>q.val){
            return lowestCommonAncestor(root.left,p,q);
        }else if(root.val<p.val&&root.val<q.val){
            return lowestCommonAncestor(root.right,p,q);
        }else return root;
    }
}

700. 二叉搜索树中的搜索

class Solution {
    //递归
    // public TreeNode searchBST(TreeNode root, int val) {
    //     if(root==null||root.val==val) return root;
    //     if(root.val>val) return searchBST(root.left,val);
    //     if(root.val<val) return searchBST(root.right,val);
    //     return null;
    // }
    //迭代
    public TreeNode searchBST(TreeNode root, int val) {
        while(root!=null){
            if(root.val>val) root=root.left;
            else if(root.val<val) root=root.right;
            else return root;
        }
        return null;
    }
}

701. 二叉搜索树中的插入操作

class Solution {
    //迭代
    public TreeNode insertIntoBST(TreeNode root, int val) {
        TreeNode inode=new TreeNode(val);
        TreeNode cur=root;//记录当前节点
        if(root==null){
            return inode;
        }
        while(true){
            if(cur.val>val){
                if(cur.left==null){
                    cur.left=inode;
                    return root;
                }else{
                    cur=cur.left;
                }
            }else if(cur.val<val){
                if(cur.right==null){
                    cur.right=inode;
                    return root;
                }else{
                    cur=cur.right;
                }
            }
        }
    }
    //递归
    public TreeNode insertIntoBST(TreeNode root, int val) {
        TreeNode inode=new TreeNode(val);
        if(root==null){
            return inode;
        }
        if(root.val>val) 
            root.left=insertIntoBST(root.left,val);
        if(root.val<val) 
            root.right=insertIntoBST(root.right,val);
        return root;
    }   

}

450. 删除二叉搜索树中的节点

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        // 第一种情况:没找到删除的节点,遍历到空节点直接返回了
        if(root==null) return null;
        if(root.val==key){
            // 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
            if(root.left==null&&root.right==null) return null; 
            // 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
            if(root.left==null) return root.right;
            // 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
            if(root.right==null) return root.left;
            // 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。
            else {
                TreeNode cur=root.right;
                while(cur.left!=null){
                    cur=cur.left;
                }
                cur.left=root.left;
                TreeNode temp=root;
                root=root.right;
                return root;
            }
        }
        if(root.val>key) root.left=deleteNode(root.left,key);
        if(root.val<key) root.right=deleteNode(root.right,key);
        return root;
    }
}

669. 修剪二叉搜索树

class Solution {
    //递归
    public TreeNode trimBST(TreeNode root, int low, int high) {
        if(root==null) return null;
        if(root.val<low){
            TreeNode right=trimBST(root.right,low,high);
            return right;
        }
        if(root.val>high){
            TreeNode left=trimBST(root.left,low,high);
            return left;
        }
        root.left=trimBST(root.left,low,high);
        root.right=trimBST(root.right,low,high);
        return root;
    }
}

108. 将有序数组转换为二叉搜索树

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        TreeNode root=traversal(nums,0,nums.length-1);
        return root;
    }
    public TreeNode traversal(int[] nums,int left,int right){
        if(left>right) return null;
        int mid=left+((right-left)/2);
        TreeNode root=new TreeNode(nums[mid]);
        root.left=traversal(nums,left,mid-1);
        root.right=traversal(nums,mid+1,right);
        return root;
    }
}

538. 把二叉搜索树转换为累加树

class Solution {
    int pre;
    public TreeNode convertBST(TreeNode root) {
        pre=0;
        traversal(root);
        return root;
        
    }
    // 递归
    public void traversal(TreeNode cur){
        if(cur==null) return;
        traversal(cur.right);
        cur.val+=pre;
        pre=cur.val;
        traversal(cur.left);
    }
    // 迭代
    public void traversal(TreeNode root) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode cur=root;
        while(cur!=null||stack.size()>0){
            if(cur!=null){
                stack.push(cur);
                cur=cur.right;
            }else{
                cur=stack.pop();
                cur.val+=pre;
                pre=cur.val;
                cur=cur.left;
            }  
        } 
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值