二叉树刷题总结

二叉树刷题总结

二叉树的基础

  • 满二叉树,二叉树节点满足,2的N次方-1的树
  • 完全二叉树,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。
  • 二叉搜索树
    • 左子树不空,则左子树的每一个节点小于根节点
    • 右子树不空,则右子树的每一个节点大于根节点
    • 左子树与右子树都满足二叉搜索树的概念
  • 平衡二叉搜索树:在二叉搜索树的技术上,增加一条,左子树右子树高度差不超过1。

二叉树的定义

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;
  	}
}

二叉树的遍历

二叉树的遍历可谓是二叉树的精髓中的精髓中的精髓,一定要好好理解好好把我。

二叉树的遍历方式
  1. 广度优先遍历
  2. 深度优先遍历
  3. 前序遍历
  4. 中序遍历
  5. 后续遍历

这五种遍历都是重要的不能再重要的遍历,一定不能背要好好理解好好琢磨。

广度遍历

在广度遍历这里,我想重点提出一句话。进入下一层遍历的时候,队列里已经没有本层的节点了。
在理解这句话之前,我的广度遍历不能分层,理解这句话后,我的广度遍历就能分层。
举个例子

    LinkedList<Integer> list;

    public void bfs_no_layer(TreeNode root){
        list = new LinkedList<Integer>();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        while (!queue.isEmpty()){
            TreeNode poll = queue.poll();
            if (poll.left != null) queue.add(poll.left);
            if (poll.right != null) queue.add(poll.right);
            list.add(poll.val);
        }
    }


    public static void main(String[] args) {
        TreeNode node1 = new TreeNode(1);
        TreeNode node2 = new TreeNode(2);
        TreeNode node3 = new TreeNode(3);
        TreeNode node4 = new TreeNode(4);
        TreeNode node5 = new TreeNode(5);
        TreeNode node6 = new TreeNode(6);
        TreeNode node7 = new TreeNode(7);

        node1.left = node2;
        node1.right = node3;
        node2.left = node4;
        node2.right = node5;
        node3.right = node7;
        node5.left = node6;

        BFS bfs = new BFS();
        bfs.bfs_no_layer(node1);

        for(int i :bfs.list){
            System.out.print(i+" ");
        }
    }

在这里也是广度遍历,但是这个广度遍历,输出的节点是没有分层的。这个是相当致命的。很多问题因此无法解决。
但是只要理解一句话进入新的一层的这个瞬间,队列里只有当前层的节点

import java.util.LinkedList;
import java.util.Queue;

public class BFS {

    LinkedList<Integer> list;

    LinkedList<LinkedList<Integer>> list2;
    public void bfs_no_layer(TreeNode root){
        list = new LinkedList<Integer>();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        while (!queue.isEmpty()){
            TreeNode poll = queue.poll();
            if (poll.left != null) queue.add(poll.left);
            if (poll.right != null) queue.add(poll.right);
            list.add(poll.val);
        }
    }

    public void bfs_have_layer(TreeNode root){
        list2 = new LinkedList<LinkedList<Integer>>();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();

        queue.add(root);
        while (!queue.isEmpty()){
            int size = queue.size();//抓住这个瞬间,记录下此时节点有多少个
            LinkedList<Integer> templist = new LinkedList<Integer>();
            while (size > 0){
                size--;
                TreeNode poll = queue.poll();
                if (poll.left != null) queue.add(poll.left);
                if (poll.right != null) queue.add(poll.right);
                templist.add(poll.val);
            }
            list2.add(templist);
        }
    }


    public static void main(String[] args) {
        TreeNode node1 = new TreeNode(1);
        TreeNode node2 = new TreeNode(2);
        TreeNode node3 = new TreeNode(3);
        TreeNode node4 = new TreeNode(4);
        TreeNode node5 = new TreeNode(5);
        TreeNode node6 = new TreeNode(6);
        TreeNode node7 = new TreeNode(7);

        node1.left = node2;
        node1.right = node3;
        node2.left = node4;
        node2.right = node5;
        node3.right = node7;
        node5.left = node6;

        BFS bfs = new BFS();
        bfs.bfs_no_layer(node1);

        bfs.bfs_have_layer(node1);

        for(int i :bfs.list){
            System.out.print(i+" ");
        }
        System.out.println();
        for (LinkedList<Integer> list : bfs.list2){
            for (int i :list){
                System.out.print(i+" ");
            }
            System.out.println();
        }
    }
}

仔细理解这段代码很重要!!!
来看一些BFS的题目

leetcode 199. 二叉树的右视图
这道题和明显,分析题目,就知道要找到每一层最右边的节点。分层次的层次遍历,很轻易就可以做到。只需要在每一层遍历(第二个小循环)中,记录最后一个被遍历到的节点即可

public List<Integer> rightSideView(TreeNode root) {
        List<Integer> list = new LinkedList<Integer>();
        if(root == null) return list;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        while (!queue.isEmpty()){
            int size = queue.size();//抓住这个瞬间,记录下此时节点有多少个
            int temp = 0;
            while (size > 0){
                size--;
                TreeNode poll = queue.poll();
                if (poll.left != null) queue.add(poll.left);
                if (poll.right != null) queue.add(poll.right);
                temp = poll.val;		//在这里进行了改动.
            }
            list.add(temp);
        }
        return list;
    }

leetcode 637 层的平均值
大同小异

public List<Double> averageOfLevels(TreeNode root) {
        List<Double> list = new LinkedList<Double>();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();

        queue.add(root);
        while (!queue.isEmpty()){
            int size = queue.size();//抓住这个瞬间,记录下此时节点有多少个
            double sum = 0;
            double num = 0;
            while (size > 0){
                size--;
                TreeNode poll = queue.poll();
                if (poll.left != null) queue.add(poll.left);
                if (poll.right != null) queue.add(poll.right);
                num++;
                sum += poll.val;
            }
            list.add(sum/num);
        }
        return list;
    }

同理,最大深度,就是层次遍历很简单的应用。
最小深度就是层次遍历,遇到根节点就可以退出。这么点区别。

二叉树遍历

因为层次遍历比较特殊,单独拿出来说。
二叉树的深度遍历,规定好方向其实就是变成先序遍历。两者没有本质的区别。

如何递归

在此之前,我想先表明,递归是什么操作。如何递归。在我们准备一个递归的时候需要解决以下几个问题。

  1. 参数:应该选择什么参数来进入迭代。
  2. 递归的终止条件:什么时候return
  3. 返回值
  4. 最后才是业务逻辑
二叉树的前序遍历

前序遍历的顺序:根、左子树、右子树。

    LinkedList<Integer> list = new LinkedList<Integer>();
    public List<Integer> preorderTraversal(TreeNode root) {
        recur(root);
        return list;
    }
    public void recur(TreeNode root){
        if (root == null) return;
        list.add(root.val);
        recur(root.left);
        recur(root.right);
    }

值得注意的是,为什么要分两个函数来写。就是因为第一个函数的返回值不同。就很多考点都是在这里,就是一个前序遍历,你怎么用这个前序遍历获得你想要的东西,this is point。

给出前序遍历的递归写法。

    public List<Integer> preorderTraversal(TreeNode root) {
        LinkedList<Integer> res = new LinkedList<Integer>();
        if (root == null) return res;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.add(root);
        while (!stack.isEmpty()){
            System.out.println(1);
            TreeNode poll = stack.pop();
            res.add(poll.val);
            if(poll.right != null) stack.add(poll.right);
            if(poll.left != null) stack.add(poll.left);
        }
        return res;
    }

很简单,因为前序遍历的顺序和代码的执行顺序是相同的,只需要先访问节点,再去放入就可以了。

二叉树的中序遍历

二叉树的中序遍历的递归手段和先序遍历没有本质上的区别,都是照猫画虎,就业务逻辑上有一点点小差别

    LinkedList<Integer> list = new LinkedList<Integer>();
    public List<Integer> inorderTraversal(TreeNode root) {
        recur(root);
        return list;
    }
    public void recur(TreeNode root){
        if (root == null) return;
        recur(root.left);
        list.add(root.val);
        recur(root.right);
    }

需要注意的是,其实在二叉树的题目中,很多递归的终止条件有两个反复出现的点

  1. root == null
  2. root.left == null && root.right == null

二叉树的中序遍历的迭代版本。如果害按照前序遍历的逻辑去写中序遍历的迭代算法是行不通的。

    public List<Integer> inorderTraversal_2(TreeNode root) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        LinkedList<Integer> res = new LinkedList<Integer>();
        stack.add(root);
        TreeNode cur = root;
        while (cur!=null || !stack.isEmpty()){
            if (cur == null){
                //说明此时遍历到上一个是叶子结点
                cur = stack.pop();
                res.add(cur.val);
                cur = cur.right;
            }else {
                stack.add(cur);
                cur = cur.left;
            }
        }
        return res;
    }

在中序遍历中,我们采用了一个cur来记录当前的节点。并且在栈中保存了上一个节点。如果采用cur不等于null一直向左遍历的特点。当cur == null的时候,那上一个节点一定是当前时间最左,可以放出来进行访问。此时再记录右子树。整体是这样的逻辑。

二叉树的后续遍历

递归手段

    LinkedList<Integer> list = new LinkedList<Integer>();
    public List<Integer> postorderTraversal(TreeNode root) {
        recur(root);
        return list;
    }
    public void recur(TreeNode root){
        if (root == null) return;
        recur(root.left);
        recur(root.right);
        list.add(root.val);
    }

但是二叉树后序遍历的递归手法真的很巧妙,对于前序遍历,我们访问的顺序是根,左子树,右子树,对于后续遍历访问的顺序是左子树,右子树,根,如果有一个访问顺序是根, 右子树,左子树,那么颠倒顺序就是后续遍历。

    public List<Integer> postorderTraversal_2(TreeNode root) {
        LinkedList<Integer> list = new LinkedList<Integer>();
        if (root == null) return list;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.add(root);
        while (!stack.isEmpty()){
            TreeNode pop = stack.pop();
            list.add(pop.val);
            if (pop.left != null) stack.add(pop.left);
            if (pop.right != null) stack.add(pop.right);
        }
        Collections.reverse(list);
        return list;
    }

掌握了这些,接下来就可以开始愉快的刷题之旅啦

  1. 翻转二叉树
    这道题用递归的方法做。对每一颗树都调换一下左子树和右子树
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return null;
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        invertTree(root.right);
        invertTree(root.left);
        return root;
    }

这道题为什么会想到递归的思路呢。我现在对于二叉树的递归思路都是从顶到下的。什么意思,就是说我先看root的left与right调换会有什么效果,再看root.left的left和right调换会有什么效果。目前对于二叉树的递归我是这么理解的。

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

    public int countNodes(TreeNode root) {
        if (root == null) return 0;
        int num = 0;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);

        while (!queue.isEmpty()){
            TreeNode poll = queue.poll();
            num++;
            if (poll.left != null) queue.add(poll.left);
            if (poll.right != null) queue.add(poll.right);
        }
        return num;
    }

这道题的深度遍历和广度遍历我都写了。但是利用完全二叉树性质的那个方法我还没研究。

  1. 平衡二叉树
    public boolean isBalanced(TreeNode root) {
        if (root == null) return true;
        int left = getDeep(root.left);
        int right = getDeep(root.right);
        boolean tag = false;
        if (Math.abs(left - right) <= 1) tag = true;
        return tag && isBalanced(root.left) && isBalanced(root.right);
    }
    public int getDeep(TreeNode root){
        if (root == null) return 0;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        int num_layer = 0;
        while (!queue.isEmpty()){
            int size = queue.size();
            while (size > 0){
                size--;
                TreeNode poll = queue.poll();
                if (poll.left != null) queue.add(poll.left);
                if (poll.right != null) queue.add(poll.right);
            }
            num_layer++;
        }
        return num_layer;
    }

这道题,我一开始的思路是,用层次遍历,找到最短的层和最大的层,但是后面我发现,我这个思路有一个巨大的bug,就是我只考虑到了root节点是不是平衡树,我没有考虑到子树的是不是平衡树。所以我采用了递归的手段。有没有发现,其实递归最大的好处是,能保证每一颗树(树的组成部分)是复合递归的规律的!这个是递归的核心。

257 记录二叉树所有路径
这道题我愿称之为很考验基础功的一道题

    List<String> res = new LinkedList<String>();
    public List<String> binaryTreePaths(TreeNode root) {
        if (root == null) return res;
        String str = String.valueOf(root.val);
        if (root.left == null && root.right == null){
            res.add(str);
            return res;
        }
        recur(root.left,str);
        recur(root.right,str);
        return res;
    }
    public void recur(TreeNode root,String path){
        if(root == null) return;
        path  = path + "->"+root.val;
        if (root.left == null && root.right == null){
            res.add(path);
            return;
        }
        recur(root.left,path);
        recur(root.right,path);
    }
  1. 这道题的思路还是很简单的,就是一个深度遍历循环,没什么特点。
  2. 考验对于首个节点的把握程度。怎么去把握第一个节点是关键!对于这种第一个节点不能递归处理的,就把他放在主程序中,副程序递归左子树和右子树就可以。
  3. 对于终止的条件的把握,我第一次作对了,第二次做错了,就是因为对于终止条件的把我不够明确。所谓终止条件,无非就两个,root == null 和root.leftnull&&root.rightnull。在这里如何把我还是很考验人的。

404. 左叶子之和 字节算法题的面试真题

    int sum = 0;
    public int sumOfLeftLeaves(TreeNode root) {
        if (root == null) return 0;
        recur(root.left,true);
        recur(root.right,false);
        return sum;
    }
    public void recur(TreeNode root,boolean tag){
        //在recur中要做的很简单
        //1.判断是不是叶子结点
        //2.判断是不是左节点
        if (root == null) return;
        if (root.left == null && root.right ==null){
            if (tag) sum += root.val;
        }
        recur(root.left,true);
        recur(root.right,false);
        
    }

这这道题里面,每一次迭代遍历需要做两件事

  1. 判断这个节点是不是叶子节点
  2. 判断这个节点是不是左节点。在这里判断是不是左节点,我用了一个tag来做辅助。
    值得注意的是,在这里我用了两个终止条件,之所以这么做可以节省一些些代码。

513.找树左下角的值
也不知道这道题为什么就是中等难度的了= - =我觉得还挺简单啊。

    public int findBottomLeftValue(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        LinkedList<Integer> list = null;
        while (!queue.isEmpty()){
            list = new LinkedList<Integer>();
            int size = queue.size();
            while (size >0){
                size--;
                TreeNode poll = queue.poll();
                list.add(poll.val);
                if(poll.left != null) queue.add(poll.left);
                if(poll.right != null) queue.add(poll.right);
            }
        }
        return list.get(0);
    }

112.路径总和
这道题还是考验基础是不是扎实。本质上就是一个深度循环遍历。我采用了两种方式来写
第一种,不额外增加空间.

    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) return false;
        if (root.left == null && root.right == null){
            if (root.val == targetSum) return true;
            else return false;
        }
        return recur(root,targetSum,0);
    }
    public boolean recur(TreeNode root,int targetSum,int path){
        path += root.val;
        if (root.left == null && root.right ==null){
            if (path == targetSum) return true;
            else return false;
        }
        boolean tag1 = false;
        boolean tag2 = false;
        if (root.left != null) tag1 = recur(root.left,targetSum,path);

        if (root.right != null) tag2 = recur(root.right,targetSum,path);
        return tag1 || tag2;
    }

第二种,增加了一个list来记录路径之和

    List<Integer> list = new LinkedList<Integer>();

    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null) return false;
        recure(root,0);
        for (int i : list){
            if (i == targetSum)
                return true;
        }
        return false;
    }

    public void recure(TreeNode root,int path){
        if (root.right == null && root.left == null){
            path += root.val;
            list.add(path);
            return;
        }
        path = path + root.val;
        if (root.left != null) recure(root.left,path);
        if (root.right != null) recure(root.right,path);
    }

105 从前序与中序遍历序列构造二叉树
这道题有两个难点
难点1. 逻辑不是特别好理解
难点2. 理解了逻辑之后,怎么表达出来

明确1. 前序遍历和后续遍历可以帮助我们找到根,中序遍历可以帮助我们划分左子树和右子树。
剩下的就是如何去处理。

    HashMap<Integer,Integer> map;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        //明确,前序找根,中序划分左子树和右子树
        map = new HashMap<Integer, Integer>();
        int count = 0;
        for (int i : inorder) map.put(i,count++);
        //定义一个map帮助我们来划分左子树和右子树
        return recur(preorder,inorder,0,preorder.length-1,0,inorder.length-1);
    }
    public TreeNode recur(int[] preorder,int[] inorder,int m,int n,int p,int q){
        //m n 是 先序的边界
        // p q 是 中序的边界
        //用先序找根,先序的第一个节点,就是根
        //精髓就在如何定义这个边界
        if (p > q) return null;
        TreeNode root = new TreeNode(preorder[m]);
        int index = map.get(preorder[m]);
        int num_left = index - p;
        root.left = recur(preorder,inorder,m+1,m+num_left,p,index-1);//定义给这棵树的左子树
        root.right = recur(preorder,inorder,m+num_left+1,n,index+1,q);//定义给这棵树的右子树
        return root;
    }

这道题就有很多小技巧

  1. 使用了一个hashmap来记录中序遍历的节点与对应的索引。方便划分左子树与右子树。
  2. 它的终止条件是 p > q。当p=q的时候,说明这个是一个叶子节点,他没有子节点了,当p>q的时候就跳出循环。
  3. 记录下左子树的个数,帮助划分

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

    HashMap<Integer,Integer> map;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        map = new HashMap<Integer, Integer>();
        int count = 0;
        for (int i :inorder)map.put(i,count++);
        return recur(inorder,postorder,0,inorder.length-1,0,postorder.length-1);
    }
    public TreeNode recur(int[] inorder,int[] postorder,int m,int n,int p,int q){
        //用后续遍历确定根,p q是后续遍历的界
        //用中序遍历划分左子树和右子树,m n 是中序遍历的界
        if (m>n) return null;
        TreeNode root = new TreeNode(postorder[q]);
        int index = map.get(root.val);
        int num_left = index - m;
        root.left = recur(inorder,postorder,m,index-1,p,p+num_left-1);
        root.right = recur(inorder,postorder,index+1,n,p+num_left,q-1) ;
        return root;
    }

思路是相同的,就拿来练手,关键还是左子树右子树的划分区域

654 最大二叉树
比前面两题还要简单 = - =

    HashMap<Integer,Integer> map;
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        map = new HashMap<Integer, Integer>();
        int count = 0;
        for(int i:nums) map.put(i,count++);
        return recur(nums,0,nums.length-1);
    }
    public TreeNode recur(int[] nums,int p,int q){
        if (p > q) return null;
        int max = findmax(nums,p,q);
        TreeNode root = new TreeNode(max);
        int index = map.get(max);
        System.out.println(max);
        root.left = recur(nums,p,index-1);
        root.right = recur(nums,index+1,q);
        return root;
    }
    public int findmax(int[] nums,int p,int q){
        int max = -1;
        for (int i = p;i<=q;i++){
            if (max < nums[i])
                max = nums[i];
        }
        return max;
    }

617 合并二叉树

    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if (root1 == null && root2 == null) return null;
        if (root1 == null && root2 != null) return root2;
        if (root1 != null && root2 == null) return root1;
        TreeNode root = new TreeNode(root1.val+root2.val);
        root.left = mergeTrees(root1.left,root2.left);
        root.right = mergeTrees(root1.right,root2.right);
        return root;
    }

体会这个思想,这也是我自己做出来的,很简单一个递归。我的思路很简单。在当前节点我需要做什么事情。

  1. 判断root1 root2同时为空,直接返回空,root1 root2有一个为空,则另一直接返回。root1 root2都不为空,就返回两者的和,并且继续发展左子树与右子树

700 二叉搜索树中的搜索

    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null) return null;
        if (root.val == val) return root;
        if (root.val < val) return searchBST(root.right,val);
        if (root.val > val) return searchBST(root.left,val);
        return null;
    }

很简单,就是二叉搜索树的简单遍历

验证二叉搜索树
对于这题,一开始我使用递归的思想,保证root root.left root.right的一致性,却不能保证整体,只考虑了局部。
第二个思路

 public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        if (root.left == null && root.right!=null) return recur_1(root.left,root.val) && recur_2(root.right,root.val) && isValidBST(root.right);
        if (root.left != null && root.right ==null) return recur_1(root.left,root.val) && recur_2(root.right,root.val) && isValidBST(root.left);
        return recur_1(root.left,root.val) && recur_2(root.right,root.val) && isValidBST(root.left) && isValidBST(root.right);
    }
    public boolean recur_1(TreeNode root,int val){
        if (root == null) return true;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        while (!queue.isEmpty()){
            TreeNode poll = queue.poll();
            if (poll.val >= val ) return false;
            if (poll.left != null) queue.add(root.left);
            if (poll.right != null) queue.add(root.right);
        }
        return true;
    }
    public boolean recur_2(TreeNode root,int val){
        if (root == null) return true;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        while (!queue.isEmpty()){
            TreeNode poll = queue.poll();
            if (poll.val <= val ) return false;
            if (poll.left != null) queue.add(root.left);
            if (poll.right != null) queue.add(root.right);
        }
        return true;
    }

暴力求解。对于每一个root,保证左子树全部节点小于root节点,对于右子树保证所有节点大于root节点。这样会造成很多次无效计算。
这道题关键在于二叉树的中序遍历是有序的这一点。

    LinkedList<Integer> list = new LinkedList<Integer>();

    public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        int pre = -1;
        for (int i = 0;i<list.size();i++){
            if (i == 0) {
                pre = list.get(i);
                continue;
            }
            if (list.get(i) <= pre) return false;
            pre = list.get(i);
        }
        return true;
    }
    public void recur(TreeNode root){
        if (root == null) return;
        recur(root.left);
        list.add(root.val);
        recur(root.right);
    }

我这里是先记录了搜索二叉树,中序遍历的路径。再对路径进行比较

501 二叉搜索树中的众数

    LinkedList<Integer> list = new LinkedList<Integer>();
    public int[] findMode(TreeNode root) {
        LinkedList<Integer> list_2 = new LinkedList<Integer>();
        HashMap<Integer,Integer> map = new HashMap<Integer, Integer>();
        int pre = -1;
        int category = 1;
        int max_category = 1;
        for (int i = 0;i < list_2.size();i++){
            if (i == 0)
                pre = list_2.get(i);
            if (list_2.get(i) == pre){
                category++;
            }else {
                map.put(pre,category);
                System.out.println(pre);
                System.out.println(category);
                if (max_category < category)
                    max_category = category;
                pre = list.get(i);
                category = 1;
            }
        }
        for (Map.Entry<Integer,Integer>entry:map.entrySet()){
            if (entry.getValue() == max_category)
                list.add(entry.getKey());
        }
        int[] res = new int[list.size()];
        for (int i =0;i<list.size();i++){
            res[i] = list.get(i);
        }
        return res;
    }
    public void recur(TreeNode root){
        if (root == null) return;
        recur(root.left);
        list.add(root.val);
        recur(root.right);
    }

思路,这题我没通过,不想改了,脑壳能。
思路1就是首先找到顺序,第二统计出现频率,第三找到频率最高的几个数组成数组输出。

236 二叉树的最近公共祖先
我的思路很简单,虽然没有通过测试,主要是因为我的算法效率太低了,能解决问题是能的,这道题的第30个样例,树太大了,直接让我gg
我的思路很简单,第一步找到所有的公共祖先,放进一个列表,求这个这些祖先在哪一层。找到层数最大的,返回。这就是我的思路

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        LinkedList<TreeNode> list = new LinkedList<TreeNode>();
        queue.add(root);
        while (!queue.isEmpty()){
            TreeNode poll = queue.poll();
            if (isArrive(poll,p) && isArrive(poll,q)) list.add(poll);
            if (poll.left != null) queue.add(poll.left);
            if (poll.right != null) queue.add(poll.right);
        }
        int layer = -1;
        for (TreeNode treeNode:list){
            System.out.println(treeNode.val);
            int i = num_layer(root, treeNode);
            if (i>layer) layer = i;
        }
        for (TreeNode treeNode:list){
            if (layer == num_layer(root,treeNode))
                return treeNode;
        }
        return null;
    }
    public boolean isArrive(TreeNode root,TreeNode p){
        if (root == null) return false;
        boolean tag = false;
        if (root.val == p.val)
            tag = true;
        return tag || isArrive(root.left,p) || isArrive(root.right,p);
    }

但是这样子做明显不符合要求。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值