【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树)

导读:本篇文章讲解 【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

目录

1. 二叉树的前序遍历

2. 二叉树的中序遍历

3. 二叉树的后序遍历

4. 求二叉树的层序遍历

5. 按之字形顺序打印二叉树

6. 二叉树的最大深度

7. 二叉树中和为某一值的路径(一)

8.  二叉搜索树与双向链表

9. 判断是不是二叉搜索树


1. 二叉树的前序遍历

题目链接:二叉树的前序遍历_牛客题霸_牛客网 (nowcoder.com)

题目要求:

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树)

题目分析:

二叉树的前序遍历. 根左右

这里需要返回的是一个数组,如果直接用数组保存结点值的话,不好放进去,而且数组大小也不好直接写出.

最好的是可以用一个 List数组 add放, 最后转移到数组中去

上代码

import java.util.*;

public class Solution {
    public int[] preorderTraversal (TreeNode root) {
        List<Integer> list = new ArrayList<>();
        preOrder(list, root);
        int[] arr = new int[list.size()];
        for(int i = 0; i < arr.length; i++) {
            arr[i] = list.get(i);
        }
        return arr;
    }
    private void preOrder(List<Integer> list,TreeNode root) {
        if(root == null) {
            return;
        }
        list.add(root.val);
        preOrder(list,root.left);
        preOrder(list,root.right);
    }
}

2. 二叉树的中序遍历

题目链接:二叉树的中序遍历_牛客题霸_牛客网 (nowcoder.com)

题目要求:

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树)

题目分析:

和前序遍历类似,将每个结点的 val 放入 list 中, 中序遍历是 左 根 右

最后转移到 数组中返回

上代码

import java.util.*;

public class Solution {
    public int[] inorderTraversal (TreeNode root) {
        List<Integer> list = new ArrayList<>();
        inorder(root,list);
        int[] arr = new int[list.size()];
        for(int i = 0; i < arr.length; i++) {
            arr[i] = list.get(i);
        }
        return arr;
    }
    private void inorder(TreeNode root,List<Integer> list) {
        if(root == null) {
            return;
        }
        inorder(root.left,list);
        list.add(root.val);
        inorder(root.right,list);
    }
}

3. 二叉树的后序遍历

题目链接:二叉树的后序遍历_牛客题霸_牛客网 (nowcoder.com)

题目要求:

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树)

上代码

import java.util.*;

public class Solution {
    public int[] postorderTraversal (TreeNode root) {
        List<Integer> list = new ArrayList<>();
        postorder(root,list);
        int[] arr = new int[list.size()];
        for(int i = 0; i < arr.length; i++) {
            arr[i] = list.get(i);
        }
        return arr;
    }
    private void postorder(TreeNode root,List<Integer> list) {
        if(root == null) {
            return;
        }
        postorder(root.left,list);
        postorder(root.right,list);
        list.add(root.val);
    }
}

4. 求二叉树的层序遍历

题目链接:求二叉树的层序遍历_牛客题霸_牛客网 (nowcoder.com)

题目要求:

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树) 题目分析:

层序遍历,首先考虑的是用队列来做

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树)

 具体的思考流程,写代码的步骤如下:

  1. 先创建一个队列,将根节点入队, 然后出队,在出队过程中,把节点的左右子树结点入队
  2. 但是现在题目中的要求是返回一个 类似于二维数组的ArrayList结构, 也就是要确定二叉树中每一层结点的个数, 每一层结点的个数也就是 队列元素的个数
  3. 可以再创建一个ArrayList数组,用来放每一层的结点, 前面已经确定了每层结点的个数, 所以可以写一个for循环根据每层元素个数, 出队,并把当前节点的左右子树结点入队, 当把这层结点的元素出队完,此时队列中元素的个数,也就是下一层结点的个数
  4. 最后要注意的是,在上一步 for 循环中, 把出队的元素要保存到用来存放每层结点的 ArrayList 中,当 for 循环完毕,也就是这层遍历完成了,就要将这个ArrayList 数组放在二维数组的一层中, 当队列为空时,意味着层序遍历完成, 那就返回二维数组

上代码

import java.util.*;
public class Solution {
    public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();

        if(root == null) {
            return res;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        //根节点入队
        queue.add(root);

        while(!queue.isEmpty()) {
            //一层的结果
            ArrayList<Integer> level = new ArrayList<>();
            int levelCount = queue.size();//每一层的数量

            //添加一层节点到List中
            for(int i = 0; i < levelCount; i++) {
            //节点出队
            TreeNode node = queue.remove();

            //节点的左子树入队
            if(node.left != null) {
                queue.add(node.left);
            }
            //节点的右子树入队
            if(node.right != null) {
                queue.add(node.right);
            }
            level.add(node.val);
            }                     
        res.add(level);   
        }
    return res;
    }
}

5. 按之字形顺序打印二叉树

题目链接:按之字形顺序打印二叉树_牛客题霸_牛客网 (nowcoder.com)

题目要求:

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树)

题目分析:

正常的层序遍历中遍历的每一行都是从左到右的, 而这道题是一行从左到右,一行从右到左,

具体的做法和上一题一样,都是用队列的,每遍历到一行就放入到二维数组中, 不同的是因为每行的遍历顺序是交叉相反的,

所以可以定义一个变量用来标识当前队列遍历到这样层的状态

比如定义个 ret = false  队列每遍历完一行就取 !ret,如果当前ret是 true就正常放入二维数组中,如果当前 ret 是 false 就用 Collections.reverse(队列遍历到的这一层) 反转保存这一行数据的list

上代码

import java.util.*;
public class Solution {
    public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(pRoot == null) {
            return res;
        }
        Queue<TreeNode> queue = new LinkedList<>();

        //根节点入队
        queue.add(pRoot);
        boolean ret = true;
        while(!queue.isEmpty()) {
            //每一层的结点
            ArrayList<Integer> arr = new ArrayList<>();
            int size = queue.size();
            ret = !ret;
            for(int i = 0; i < size; i++) {
                //节点出队
                TreeNode node = queue.remove();
                //左子树入队
                if(node.left != null) {
                    queue.add(node.left);
                }
                //右子树入队
                if(node.right != null) {
                    queue.add(node.right);
                }
                arr.add(node.val);
            }
            if(ret) {
                Collections.reverse(arr);
            }
            res.add(arr);
        }
        return res;
    }
}


6. 二叉树的最大深度

题目链接:二叉树的最大深度_牛客题霸_牛客网 (nowcoder.com)

题目要求:

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树)

题目分析:

这道题最简单的代码就是用递归来做,

往下遍历左子树和右子树,每遍历到一层就+1,找到遍历最深的那个

上代码

import java.util.*;
public class Solution {
    public int maxDepth (TreeNode root) {
        if(root == null) {
            return 0;
        }
        return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
    }
}

也可以用层序遍历来做

上一题是层序遍历二叉树,遍历完每一层然后返回给二维数组,然后打印出来

这道题如果用层序遍历来做的话,还是考虑使用队列,不过这道题只需要定义一个变量count,每遍历完一层就 count++,最后层序遍历完成,返回count

    public int maxDepth (TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        if (root == null) {
            return 0;
        }
        int count = 0;
        queue.add(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.remove();
                if (node.left != null) {
                    queue.add(node.left);
                }
                if (node.right != null) {
                    queue.add(node.right);
                }
            }
            count++;
        }
        return count;
    }

7. 二叉树中和为某一值的路径(一)

题目链接:二叉树中和为某一值的路径(一)_牛客题霸_牛客网 (nowcoder.com)

题目要求:

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树) 题目分析:

(1) 递归

上代码

import java.util.*;

public class Solution {
    public boolean hasPathSum (TreeNode root, int sum) {
        if(root == null) {
            return false;
        }
        if(root.left == null && root.right == null && sum - root.val == 0) {
            return true;
        }
        return hasPathSum(root.left, sum-root.val) || hasPathSum(root.right, sum-root.val);
    }
}

(2) 栈 + DFS

import java.util.*;

public class Solution {
    public boolean hasPathSum (TreeNode root, int sum) {
        if(root == null) {
            return false;
        }
        Stack<TreeNode> s1 = new Stack<>();
        Stack<Integer> s2 = new Stack<>();
        s1.add(root);
        s2.add(root.val);
        while(!s1.isEmpty()) {
            TreeNode node = s1.pop();
            int sum_ret = s2.pop();
            if(node.left == null && node.right == null && sum_ret == sum) {
                return true;
            }
            if(node.left != null) {
                s1.add(node.left);
                s2.add(node.left.val + sum_ret);
            }
            if(node.right != null) {
                s1.add(node.right);
                s2.add(node.right.val + sum_ret);
            }
        }
        return false;
    }
}

8.  二叉搜索树与双向链表

题目链接: 二叉搜索树与双向链表_牛客题霸_牛客网 (nowcoder.com)

题目要求:

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树)

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树)

题目分析:

(1) 递归+中序遍历

  1. 创建两个指针, head 头指针, pre 指向当前节点的前一个节点
  2. 中序遍历就要先递归到最左,然后当 pre为 null 时就初始化 head 和 pre
  3. 下面就是处理中间结点了,因为是双向链表,并且pre表示当前节点的前一个节点,这样就可以让 pre,right = 当前节点,  当前节点.left = pre,  最后再把 pre 更新为当结点
  4. 最后递归进入右子树
  5. 递归结束条件就是结点为null

上代码

public class Solution {
        TreeNode head = null;
        TreeNode pre = null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree == null) {
            return null;
        }
        Convert(pRootOfTree.left);
        if(pre == null) {
            head = pRootOfTree;
            pre = pRootOfTree;
        } else {
            pre.right = pRootOfTree;
            pRootOfTree.left = pre;
            pre = pRootOfTree;
        }
        Convert(pRootOfTree.right);
        return head;

    }
}

(2) 栈 + 中序遍历

  1. 创建 head为头, pre 表示当前节点的前一个节点 , 创建一个标志位如果第一次到达最左端,那就为true,否则为false
  2. 判断树为 null 的情况
  3. 创建一个栈, 依次先把左结点加入到栈中,直到此时二叉树遍历到最左节点停下,此时出栈,出栈的这个节点就是最左节点
  4. 然后根据这个最左结点, 初始化head  pre, 循环进入根节点开始连接
  5. 最后进入到右子树
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree == null) {
            return null;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode head = null;
        TreeNode pre = null;
        //标识此时第一次遍历到最左
        boolean isFirst = true;
        while(pRootOfTree != null || !stack.isEmpty()) {
            //连续放入左节点
            while(pRootOfTree != null) {
                stack.push(pRootOfTree);
                pRootOfTree = pRootOfTree.left;
            }
            //取出最左元素 此时为表头
            pRootOfTree = stack.pop();
            if(isFirst) {
                head = pRootOfTree;
                pre = head;
                isFirst = false;
            } else {
                //pre 当前节点的上一个节点,将当前节点和pre连接,并更新pre
                pre.right = pRootOfTree;
                pRootOfTree.left = pre;
                pre = pRootOfTree;
            }
            pRootOfTree = pRootOfTree.right;
        }
        return head;
    }

9. 判断是不是二叉搜索树

题目链接 判断是不是二叉搜索树_牛客题霸_牛客网 (nowcoder.com)

题目要求 

【刷题笔记】之牛客面试必刷TOP101(二叉树的前.中.后.层序遍历+按之字形顺序打印二叉树+二叉树的最大深度+二叉树中和为某一值的路径(一)+二叉搜索树与双向链表+判断是不是二叉搜索树)

 题目分析

(1) 栈+数组

  1. 创建栈用来遍历二叉树, 创建 ArrayList数组 用来保存中序遍历的结果(如果数组为递增的就是二叉搜索树)
  2. 下面就是给栈中遍历放元素结点,先放左节点,直到当前节点为null
  3. 出栈,此时这个出栈的元素最左节点,把这个节点的val 放入数组中
  4. 然后将右边结点也加入到栈中,同样进入右子树后,也是先访问最右结点
  5. 到最后所有结点遍历完后,就遍历数组,看数组是不是递增的

上代码 

    public boolean isValidBST (TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        ArrayList<Integer> arr = new ArrayList<>();
        TreeNode head = root;
        while(head != null || !stack.isEmpty()) {
            while(head != null) {
                stack.push(head);
                head = head.left;
            }
            head = stack.pop();
            //将当前结点加入到数组中
            arr.add(head.val);

            head = head.right;
        } 
        //看这个数组是不是递增的
        for(int i = 1; i < arr.size(); i++) {
            if(arr.get(i-1) > arr.get(i)) {
                return false;
            }
        }
        return true;
    }

(2) 递归

  1. 创建一个pre 用来保存当前节点的上一个节点,初始化为最小值
  2. 下面开始递归左子树,看是不是BST
  3. 判断当前节点是不是小于前置节点,更新前置节点
  4. 最后由右子树的后面节点决定
    Integer pre = Integer.MIN_VALUE;
    public boolean isValidBST (TreeNode root) {
        if(root == null) {
            return true;
        }
        //先左递归,如果左树不为BST,就返回false
        if(!isValidBST(root.left)) {
            return false;
        }
        //当 pre(前一个值) > 当前节点值, 返回 false
        if(pre > root.val) {
            return false;
        }
        //如果满足前一个值小于当前值,就更新pre
        pre = root.val;
        return isValidBST(root.right);
    }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/91192.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!