自学内容网 自学内容网

leetcode刷题——二叉树(1)

目录

1、递归遍历二叉树

2、迭代法遍历二叉树(通过while循环)

3、二叉树的层序遍历

4、二叉树的层次遍历 II

5、二叉树的右视图

6、二叉树的层平均值

7、N叉树的层序遍历

8、在每个树行中找最大值

9、填充每个节点的下一个右侧节点指针

10、填充每个节点的下一个右侧节点指针II

11、二叉树的最大深度

12、二叉树的最小深度


二叉树有两种主要的形式:满二叉树和完全二叉树、二叉搜索树、二叉平衡树

遍历方式

  • 深度优先遍历
    • 前序遍历(递归法,迭代法)中左右
    • 中序遍历(递归法,迭代法)左中右
    • 后序遍历(递归法,迭代法)左右中
    • 前中右代表中间节点的位置
  • 广度优先遍历
    • 层次遍历(迭代法)

1、递归遍历二叉树

  1. 确定递归函数的参数和返回值

  2. 确定终止条件

  3. 确定单层递归的逻辑

class TreeNode{
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(){};
    TreeNode(int val){this.val=val;}
}
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        preOrder(root,res);
        return res;
    }

    //前序遍历:中左右
    public void preOrder(TreeNode cur,List<Integer> res){
        if(cur==null){return;}
        res.add(cur.val);
        preOrder(cur.left,res);
        preOrder(cur.right,res);
    }

     //后序遍历:左右中
    public void postOrder(TreeNode cur,List<Integer> res){
        if(cur==null){return;}
       
        postOrder(cur.left,res);
        postOrder(cur.right,res); 
        res.add(cur.val);
    }

     //中序遍历:左中右
    public void inOrder(TreeNode cur,List<Integer> res){
        if(cur==null){return;}
       
        inOrder(cur.left,res);
        res.add(cur.val);
        inOrder(cur.right,res); 
        
    }
}

2、迭代法遍历二叉树(通过while循环)

class Solution {

//前序迭代:先把中间节点入栈,然后弹出再把右边的节点入栈,再把左节点入栈,才能保证弹出的顺序是中左右
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        Stack<TreeNode> ss=new Stack();
        // stack方法 peek pop push empty 继承vector
        if (root==null) return res;
        TreeNode cur=root;
        ss.push(cur);
        while(!ss.empty()){
            TreeNode node=ss.pop();
            res.add(node.val);
            if(node.right!=null) ss.push(node.right);
            if(node.left!=null) ss.push(node.left);
        }
        return res;
        
    }

public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        Stack<TreeNode> ss=new Stack<>();
        if(root==null) return res;
        TreeNode cur=root;
        //中序遍历,左中右 
        while(!ss.empty() || cur!=null){
            //不断的把左节点入栈
            if(cur!=null) {
                ss.push(cur);
                cur=cur.left;
            }
            //左节点为空,那就弹出当前的中间节点,然后把指针挪到右边节点
            else{
                cur=ss.pop();
                res.add(cur.val);
                cur=cur.right;
                
            }
        }
        return res;

}


public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        Stack<TreeNode> ss=new Stack<>();
        if(root==null) return res;
        TreeNode cur=root;
        ss.push(cur);
        while(cur!=null || !ss.empty()){
            //左右中的顺序

            //先遍历完左边的节点,同时要切断树之间的联系,免得下次重复添加节点
            if(cur.left!=null){
                ss.push(cur.left);
                cur.left=null;
                cur=ss.peek();
                continue;
            }
            //遍历完右边的节点,同时要切断树之间的联系,免得下次重复添加节点
            if(cur.right!=null){
                ss.push(cur.right);
                cur.right=null;
                cur=ss.peek();
            }
            左右遍历结束后,就弹出中间节点,然后回到栈顶的下一个节点
            else{
                cur=ss.pop();
                res.add(cur.val);
                System.out.print(cur.val);
                if(!ss.empty()) 
                    cur=ss.peek();
                else{
                    cur=null;
                }
            }
            
        }

    
    return res;
        
    }


public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        Stack<TreeNode> ss=new Stack<>();
        if(root==null) return res;
        TreeNode cur=root;
        ss.push(cur);
        //前序遍历是中左右,那改变左右顺序变成 中右左  最后反转就是左右中后序遍历
        while(!ss.empty()){
            
            cur=ss.pop();
            res.add(cur.val);
            if(cur.left!=null) ss.push(cur.left);
            if(cur.right!=null) ss.push(cur.right);
        }
        Collections.reverse(res);
        return res;
}

3、二叉树的层序遍历

class Solution {

    public  List<List<Integer>> res=new ArrayList<>();
    public List<List<Integer>> levelOrder(TreeNode root) {
        //queue方法 offer peek poll  linkedlist有size
        Queue<TreeNode> qq=new LinkedList<>();
        if(root==null) return res;
        qq.offer(root);
        while(qq.size()!=0){
            //len代表每一层的节点数量
            int len=qq.size();
            List<Integer> tem=new ArrayList<>();
            while(len>0){
                TreeNode node=qq.poll();
                tem.add(node.val);
                if(node.left!=null) qq.offer(node.left);
                if(node.right!=null) qq.offer(node.right);
                len--;
            }
            res.add(tem);
        }
        return res;

        
    }
}

4、二叉树的层次遍历 II

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

class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        Queue<TreeNode> qq=new LinkedList<>();
        LinkedList<List<Integer>> res=new LinkedList<>();
        //queue的运行类型是链表,但是还是只能使用queue定义的方法 offer add peek poll remove 多态
        //LinkedList双链表实现 dequeue 和list 方法addFirst addLast getFirst removeFirst
        if(root==null) return res;
        qq.add(root);
        while(!qq.isEmpty()){
            List<Integer> tem=new LinkedList<>();
            int len=qq.size();
            while(len-->0){
                TreeNode node=qq.poll();
                tem.add(node.val);
                if(node.left!=null) qq.add(node.left);
                if(node.right!=null) qq.add(node.right);
                
            }
            res.addFirst(tem);

        }
        return res;
        
    }
}

5、二叉树的右视图

Given the root of a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        Queue<TreeNode> qq=new LinkedList<>();
        List<Integer> res=new LinkedList<>();
        if(root==null) return res;
        qq.offer(root);
        while(!qq.isEmpty()){
            int len=qq.size();
            TreeNode node=null;
            while(len-->0){
                node=qq.poll();
                if(node.left!=null) qq.offer(node.left);
                if(node.right!=null) qq.offer(node.right);
            }
            //每一层都弹出,node保留的是最右边的值
            res.add(node.val);
        }
        return res;

        
    }
}

6、二叉树的层平均值

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

class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> res=new LinkedList<>();
        Queue<TreeNode> qq=new LinkedList<>();
        if(root==null) return res;
        qq.offer(root);
         while(!qq.isEmpty()){
            int len=qq.size();
            double sum=0;
            int i=len;
            while(i-->0){
                TreeNode node=qq.poll();
                sum+=node.val;
                if(node.left!=null) qq.offer(node.left);
                if(node.right!=null) qq.offer(node.right);
            }
            //每一层都弹出,node保留的是最右边的值
            res.add(sum/len);
        }
        return res;

        
    }
}

7、N叉树的层序遍历

力扣题目链接(opens new window)

给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        Queue<Node> qq=new LinkedList<>();
        List<List<Integer>> res=new LinkedList<>();
        if(root==null) return res;
        qq.offer(root);
        while(!qq.isEmpty()){
            int len=qq.size();
            Node node=null;
            List<Integer> tem=new LinkedList();
            while(len-->0){
                node=qq.poll();
                tem.add(node.val);
                if(node.children!=null){
                    for(Node nn:node.children){
                        qq.offer(nn);
                    }
                }
            }
            //每一层都弹出,node保留的是最右边的值
            res.add(tem);
        }
        return res;

    }
}

8、在每个树行中找最大值

力扣题目链接(opens new window)

您需要在二叉树的每一行中找到最大的值。

Given the root of a binary tree, return an array of the largest value in each row of the tree (0-indexed).

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        //queue方法 offer peek poll  linkedlist有size
        Queue<TreeNode> qq=new LinkedList<>();
        List<Integer> res=new ArrayList<>();
        if(root==null) return res;
        qq.offer(root);
        while(qq.size()!=0){
            //len代表每一层的节点数量
            int len=qq.size();
            int big=qq.peek().val;
            while(len>0){
                TreeNode node=qq.poll();
                big=big>node.val?big:node.val;
                if(node.left!=null) qq.offer(node.left);
                if(node.right!=null) qq.offer(node.right);
                len--;
            }
            res.add(big);
        }
        return res;
    }
}

9、填充每个节点的下一个右侧节点指针

力扣题目链接(opens new window)

给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

初始状态下,所有 next 指针都被设置为 NULL。

/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;
    public Node next;

    public Node() {}
    
    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, Node _left, Node _right, Node _next) {
        val = _val;
        left = _left;
        right = _right;
        next = _next;
    }
};
*/

class Solution {
    public Node connect(Node root) {
        //queue方法 offer peek poll  linkedlist有size
        Queue<Node> qq=new LinkedList<>();
        
        if(root==null) return null;
        qq.offer(root);
        while(qq.size()!=0){
            //len代表每一层的节点数量
            int len=qq.size();
           
            while(len>0){
                Node node=qq.poll();
              
                if(node.left!=null) qq.offer(node.left);
                if(node.right!=null) qq.offer(node.right);
                len--;
                if(len!=0){
                    node.next=qq.peek();
                }
            }
           
        }
        return root;
        
    }
}

10、填充每个节点的下一个右侧节点指针II

力扣题目链接(opens new window)

这道题的答案和上一个一样,上一个题目是满二叉树,这道题的是普通二叉树

class Solution {
    public Node connect(Node root) {
         //queue方法 offer peek poll  linkedlist有size
        Queue<Node> qq=new LinkedList<>();
        
        if(root==null) return null;
        qq.offer(root);
        while(qq.size()!=0){
            //len代表每一层的节点数量
            int len=qq.size();
           
            while(len>0){
                Node node=qq.poll();
              
                if(node.left!=null) qq.offer(node.left);
                if(node.right!=null) qq.offer(node.right);
                len--;
                if(len!=0){
                    node.next=qq.peek();
                }
            }
           
        }
        return root;
    }
}

11、二叉树的最大深度

力扣题目链接(opens new window)

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

class Solution {
    public int maxDepth(TreeNode root) {
         //queue方法 offer peek poll  linkedlist有size
        Queue<TreeNode> qq=new LinkedList<>();    
        if(root==null) return 0;
        qq.offer(root);
        int depth=0;
        while(qq.size()!=0){
            //len代表每一层的节点数量
            int len=qq.size();         
            while(len>0){
                TreeNode node=qq.poll();
                if(node.left!=null) qq.offer(node.left);
                if(node.right!=null) qq.offer(node.right);
                len--;
                
            }
            depth++;
           
        }
        return depth;
    }
}

12、二叉树的最小深度

力扣题目链接(opens new window)

Given a binary tree, find its minimum depth.

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.

Note: A leaf is a node with no children.

class Solution {
    public int minDepth(TreeNode root) {
         //queue方法 offer peek poll  linkedlist有size
        Queue<TreeNode> qq=new LinkedList<>();    
        if(root==null) return 0;
        qq.offer(root);
        int depth=0;
        while(qq.size()!=0){
            //len代表每一层的节点数量
            int len=qq.size();         
            while(len>0){
                TreeNode node=qq.poll();
                if(node.left!=null) qq.offer(node.left);
                if(node.right!=null) qq.offer(node.right);
                len--;
                if(node.left==null&&node.right==null){
                    return ++depth;
                }
                
            }
            depth++;
           
        }
        return depth;
    }
}


原文地址:https://blog.csdn.net/hahahahanhanhan/article/details/140751470

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!