【算法题-分类型总结】二叉树相关的算法题

1、判断平衡二叉树

思路:辅助函数输出子树长度&全局变量在两个函数内修改

public class Solution {

    private boolean flag;

     

    public boolean IsBalanced_Solution(TreeNode root) {

        if(root == null) {

            return true;

        }

        flag = true;

        getDepth(root);

        return flag;

    }

     

    public int getDepth(TreeNode root) {

        if(root == null) {

            return 0;

        }

        int L = getDepth(root.left);

        int R = getDepth(root.right);

        if(Math.abs(L - R) > 1) {

            flag = false;

            return -1;

        }

        return Math.max(L, R) + 1;

    }

}

 

2、中序遍历

思路:递归/栈实现左中右(入栈出栈)

/**

 * 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 {

    public List<Integer> inorderTraversal(TreeNode root) {

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

        inOrder(root, list);

        return list;

    }

 

    public void inOrder(TreeNode root, List<Integer> list) {

        if(root == null) {

            return;

        }

        inOrder(root.left, list);

        list.add(root.val);

        inOrder(root.right, list);

    }

}

//非递归方式

class Solution {

    public List<Integer> inorderTraversal(TreeNode root) {

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

        Stack<TreeNode> stack = new Stack<>();     //Deque<TreeNode> stack = new LinkedList<TreeNode>();

        //栈非空是isEmpty()而不是!=null

        while(root != null || !stack.isEmpty()) {

            while(root != null) {

                stack.push(root);

                root = root.left;

            }

            root = stack.pop();

            list.add(root.val);

            root = root.right;

        }

        return list;

    }

}

 

3、层序遍历

思路:队列+定义每层元素中的size

import java.util.*;

 

/*

 * public class TreeNode {

 *   int val = 0;

 *   TreeNode left = null;

 *   TreeNode right = null;

 * }

 */

 

public class Solution {

    ArrayList<ArrayList<Integer>> res = new ArrayList<>();

    /**

     *

     * @param root TreeNode类

     * @return int整型ArrayList<ArrayList<>>

     */

    public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {

        level(root);

        return res;

    }

    

    public void level(TreeNode root) {

        Queue<TreeNode> queue = new LinkedList<>();

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

        if(root == null) {

            return;

        }

        queue.add(root);

        while(!queue.isEmpty()) {

            //需要定义每一层元素的个数(队内元素个数)

            int size = queue.size();

            while(size > 0) {

                TreeNode node = queue.poll();

                list.add(node.val);

                if(node.left != null) {

                    queue.add(node.left);

                }

                if(node.right != null) {

                    queue.add(node.right);

                }

                size--;

            }

            res.add(new ArrayList<>(list));

            list = new ArrayList<>();

        }

    }

}

 

4、最近公共祖先

思路:递归实现+返回条件判断

/**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

class Solution {

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {

        if(root == null || 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) { //均为空时,说明都到达叶子结点,即没有找到

            return null;

        } else if(left != null && right != null) { //均为非空时,说明左右均找到了p或q,则返回根节点

            return root;

        } else { //否则,有一边没找到,则返回另一边

            return left == null ? right : left;

        }

    }

}

 

5、直径/节点路径长度

思路:回溯-结束条件、记录路径、做选择

/**

 * 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 {

    int max = 0;

    public int diameterOfBinaryTree(TreeNode root) {

        dfs(root);

        return max;

    }

    public int dfs(TreeNode root) {

        if(root.left == null && root.right == null) {

            return 0;

        }

        int leftSize = root.left == null ? 0 : dfs(root.left) + 1;

        int rightSize = root.right == null ? 0 :dfs(root.right) + 1;

        max = Math.max(max, leftSize + rightSize);

        return Math.max(leftSize, rightSize);

    }

}

 

6、最大路径和

思路:根节点为空为出口&递归左右子树&max判断

/**

 * 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 {

    int res = Integer.MIN_VALUE;

    public int maxPathSum(TreeNode root) {

        maxPath(root);

        return res;

    }

    public int maxPath(TreeNode root) {

        if(root == null) {

            return 0;

        }

        int left = Math.max(maxPath(root.left), 0);

        int right = Math.max(maxPath(root.right), 0);

        res = Math.max(res, root.val + left + right);

        return root.val + Math.max(left, right);

    }

}

 

7、最大深度

思路:BFS层次遍历,使用队列记录size,每层+1/递归记录左右最大+1

/**

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

 *     }

 * }

 */

//方法1:递归

class Solution {

    public int maxDepth(TreeNode root) {

        return root == null ? 0 : Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; 

    }

}

//方法2:BFS,即层序遍历

//注意:队列和栈的使用,BFS用队列!

class Solution {

    public int maxDepth(TreeNode root) {

        if(root == null) {

            return 0;

        }

        int level = 0;

        //队列要初始化成LinkedList

        Queue<TreeNode> queue = new LinkedList<>();

        //队列添加元素用add或offer,栈用push

        queue.offer(root);

        while(!queue.isEmpty()) {

            int size = queue.size();

            level++;

            for(int i = 0; i < size; i++) {

                //队列移除元素用remove/poll,栈用pop或top

                TreeNode node = queue.poll();

                if(node.left != null) {

                    queue.offer(node.left);

                }

                if(node.right != null) {

                    queue.offer(node.right);

                }

            }

        }

        return level;

    }

}

//方法3:DFS,相当于用栈

class Solution {

    private int maxLen = 0;

    public int maxDepth(TreeNode root) {

         if(root == null) {

             return 0;

         }

         dfs(root, 1);

         return maxLen;

 

    }

    public void dfs(TreeNode root, int level) {

        if(root == null) {

            return;

        }

        if(level > maxLen) {

            maxLen = level;

        }

        dfs(root.left, level + 1);

        dfs(root.right, level + 1);

    }

}

 

8、前序和中序构造二叉树

思路:辅助函数递归确定左右子树

import java.util.*;

/**

 * Definition for binary tree

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

public class Solution {

    public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {

        return reConstructBinaryTree(pre, 0 , pre.length - 1, vin, 0, vin.length - 1);

    }

    public TreeNode reConstructBinaryTree(int [] pre, int preStart, int preEnd, int [] vin, int vinStart, int vinEnd) {

        //注意:临界点是前后位置,pre和end永远不为空

        if(preStart > preEnd || vinStart > vinEnd) {

            return null;

        }

        TreeNode root = new TreeNode(pre[preStart]);

        for(int i = vinStart; i <= vinEnd; i++) {

            if(vin[i] == pre[preStart]) {

                //注意:先序的起始和结尾index,需要用vinStart和i表示

                root.left = reConstructBinaryTree(pre, preStart + 1, preStart + i - vinStart, vin, vinStart, i - 1);

                root.right = reConstructBinaryTree(pre, preStart + i - vinStart + 1, preEnd, vin, i + 1, vinEnd);

                //注意确定了node的左右子节点后,无需后续的遍历过程,直接break结束本次循环

                break;

            }

        }

        return root;

    }

}

 

9、锯齿/之字层次遍历

思路:层次遍历+记录序列奇偶

/**

 * 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 {

    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {

        List<List<Integer>> res = new ArrayList<>();

        circle(root, res, 0);

        return res;

    }

 

    public void circle(TreeNode root, List<List<Integer>> res, int level) {

        if(root == null) {

            return;

        }

        if(res.size() == level) {

            res.add(new ArrayList<>());

        }

        if((level & 1) == 1) { //相当于level/2,奇数层

            res.get(level).add(0, root.val); //奇数层插入到前面

        } else {

            res.get(level).add(root.val);

        }

        circle(root.left, res, level + 1);

        circle(root.right, res, level + 1);

    }

}

 

10、先序、中序、后序遍历

思路:递归+判空出口

方法1:递归

import java.util.*;

public class Solution {

    /**

     *

     * @param root TreeNode类 the root of binary tree

     * @return int整型二维数组

     */

    

    public int[][] threeOrders (TreeNode root) {

        List<Integer> preList = new ArrayList<>();

        List<Integer> inList = new ArrayList<>();

        List<Integer> postList = new ArrayList<>();

        preOrder(root, preList);

        inOrder(root, inList);

        postOrder(root, postList);

        int[][] res = new int[3][preList.size()];

        //转为int数组,需要用mapToInt

        res[0] = preList.stream().mapToInt(Integer::valueOf).toArray();

        res[1] = inList.stream().mapToInt(Integer::valueOf).toArray();

        res[2] = postList.stream().mapToInt(Integer::valueOf).toArray();

        return res;

    }

    

    public void preOrder(TreeNode root, List<Integer> preList) {

        if(root == null) return;

        preList.add(root.val);

        preOrder(root.left, preList);

        preOrder(root.right, preList);

    }

    

    public void inOrder(TreeNode root, List<Integer> inList) {

        if(root == null) return;

        inOrder(root.left, inList);

        inList.add(root.val);

        inOrder(root.right, inList);

    }

    

    public void postOrder(TreeNode root, List<Integer> postList) {

        if(root == null) return;

        postOrder(root.left, postList);

        postOrder(root.right, postList);

        postList.add(root.val);

    }

}

 

方法2:非递归

/**

     * 使用非递归的方法解决

     * @param root

     * @return

     */

    public int[][] threeOrders (TreeNode root) {

        if(root==null){

            return new int[0][0];

        }

        List<Integer> list1=new ArrayList<>();

        List<Integer> list2=new ArrayList<>();

        List<Integer> list3=new ArrayList<>();

        preOrder(list1,root);

        midOrder(list2,root);

        afterOrder(list3,root);

        int len = list1.size();

        int[][] res=new int[3][len];

        for (int i = 0; i < len; i++) {

            res[0][i]=list1.get(i);

        }

        for (int i = 0; i < len; i++) {

            res[1][i]=list2.get(i);

        }

        for (int i = 0; i < len; i++) {

            res[2][i]=list3.get(i);

        }

        return res;

    }

 

    /**

     * 先序遍历

     * @param list1

     * @param root

     */

    private void preOrder(List<Integer> list1, TreeNode root) {

        Stack<TreeNode> stack=new Stack<>();

        stack.push(root);

        while (!stack.isEmpty()){

            TreeNode node = stack.pop();

            list1.add(node.val);

            if(node.right!=null){

                stack.push(node.right);

            }

            if(node.left!=null){

                stack.push(node.left);

            }

        }

    }

    /**

     * 中序遍历

     * @param list2

     * @param root

     */

    private void midOrder(List<Integer> list2, TreeNode root) {

        Stack<TreeNode> stack=new Stack<>();

        while (!stack.isEmpty() || root!=null){

            while (root!=null){

                stack.push(root);

                root=root.left;

            }

            TreeNode node = stack.pop();

            list2.add(node.val);

            if(node.right!=null){

                root=node.right;

            }

        }

    }

    /**

     * 后序遍历

     * @param list3

     * @param root

     */

    private void afterOrder(List<Integer> list3, TreeNode root) {

        Stack<TreeNode> stack=new Stack<>();

        stack.push(root);

        while (!stack.isEmpty()){

            TreeNode node = stack.pop();

            list3.add(node.val);

            if(node.left!=null){

                stack.push(node.left);

            }

            if(node.right!=null){

                stack.push(node.right);

            }

        }

        Collections.reverse(list3);

    }

 

 

11、右视图

思路: 用队列找到每层的最后一个节点

1)给出树结构

/**

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

 *     }

 * }

 */

//BFS:层序遍历保留每一层的最后一个节点

class Solution {

    public List<Integer> rightSideView(TreeNode root) {

        List<Integer> res = new ArrayList<>();

        if(root == null) {

            return res;

        }

        Queue<TreeNode> queue = new LinkedList<>();

        //入队用offer

        queue.offer(root);

        while(!queue.isEmpty()) {

            int size = queue.size();

            for(int i = 0; i < size; i++) {

                TreeNode node = queue.poll();

                if(node.left != null) {

                    queue.offer(node.left);

                }

                if(node.right != null) {

                    queue.offer(node.right);

                }

                if(i == size - 1) {

                    res.add(node.val);

                }

            }

        }

        return res;

    }

}

 

//DFS:深度搜索,每一次的第一个加入

class Solution {

    public List<Integer> res = new ArrayList<>();

    public List<Integer> rightSideView(TreeNode root) {

        dfs(root, 0);

        return res;

    }

    public void dfs(TreeNode root, int depth) {

        if(root == null) {

            return;

        }

        if(depth == res.size()) {

            res.add(root.val);

        }

        depth++;

        dfs(root.right, depth);

        dfs(root.left, depth);

    }

}

 

2)给出前序和中序遍历,恢复二叉树并打印

HashMap<Integer,Integer> inOrderHashMap = new HashMap<>();

    public int[] solve (int[] xianxu, int[] zhongxu) {

        // write code here

        if (xianxu==null||zhongxu==null||xianxu.length==0||zhongxu.length==0) return new int[0];

        for (int i = 0; i < zhongxu.length; i++) {

            inOrderHashMap.put(zhongxu[i],i);

        }

        TreeNode root = buildTree(xianxu, 0, xianxu.length - 1, inOrderHashMap, 0, zhongxu.length - 1);

        Deque<TreeNode> queue = new ArrayDeque<>();

        queue.offer(root);

        int[] res = new int[xianxu.length];

        int count =0;

        while (!queue.isEmpty()){

            //拿到当前层元素个数

            int len = queue.size();

            System.out.println(len);

            for (int i = 0; i < len; i++) {

                TreeNode node = queue.poll();

                if (node.left!=null) queue.offer(node.left);

                if (node.right!=null) queue.offer(node.right);

                //到最后一个元素了

                if (i==len-1) res[count++] = node.val;

            }

        }

        //count是有效数组元素 0下标开始 跟左闭右开刚好对冲

        return Arrays.copyOfRange(res,0,count);

    }

    //inOrder: [inLeft,rootIndex-1] rootIndex [rootIndex+1,inRight]

    //preOrder: preLeft [preLeft+1,preLeft+rootIndex-inLeft] [preLeft+rootIndex-inLeft+1,preRight]

    private TreeNode buildTree(int[] xianxu, int preLeft, int preRight, HashMap<Integer, Integer> inOrderHashMap, int inLeft, int inRight) {

        //preLeft == preRight时 也要执行的 --叶子节点罢了

        if (preLeft>preRight||inLeft>inRight) return null;

        int rootIndex = inOrderHashMap.get(xianxu[preLeft]);

        TreeNode root = new TreeNode(xianxu[preLeft]);

        root.left = buildTree(xianxu, preLeft + 1, preLeft + rootIndex - inLeft, inOrderHashMap, inLeft, rootIndex - 1);

        root.right = buildTree(xianxu,preLeft+rootIndex-inLeft+1,preRight,inOrderHashMap,rootIndex+1,inRight);

        return root;

    }

 

12、前序遍历非递归

思路:用栈和res实现

/**

 * 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 {

    List<Integer> res = new ArrayList<>();

    public List<Integer> preorderTraversal(TreeNode root) {

        preOrder(root);

        return res;

    }

 

    public void preOrder(TreeNode root) {

        if(root == null) {

            return;

        }

        Stack<TreeNode> stack = new Stack<>();

        //表示栈非空需要使用函数

        while(!stack.isEmpty() || root != null) {

            while(root != null) { //栈内元素可能为空,只剩一个root,右子树

                res.add(root.val);

                stack.push(root);

                root = root.left;

            }

            root = stack.pop().right;

        }

    }

}

 

13、根到叶节点数字之和

思路:根计算&递归计算左右子树

//递归求和

/**

 * 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 {

    private int sum;

    public int sumNumbers(TreeNode root) {

        sum = 0;

        //初始传递0

        sumNode(root, 0);

        return sum;

    }

    public void sumNode(TreeNode root, int val) {

        if(root == null) {

            return;

        }

        val = val * 10 + root.val;

        //加的条件是当前节点为最后一个节点

        if(root.left == null && root.right == null) {

            sum += val;

        }

        sumNode(root.left, val);

        sumNode(root.right, val);

    }

}

 

14、根到叶等于目标值的路径

思路:DFS深度优先搜索

/**

 * 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 {

    private List<List<Integer>> res;

    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {

        res = new ArrayList<>();

        List<Integer> ans = new ArrayList<>();

        dfs(root, ans, targetSum, 0);

        return res;

    }

    public void dfs(TreeNode node, List<Integer> ans, int targetSum, int num) {

        if(node == null) {

            return;

        }

        if(node.left == null && node.right == null && node.val + num == targetSum) {

            ans.add(node.val);

            res.add(new ArrayList(ans));

            ans.remove(ans.size() - 1);

            return;

        }

        ans.add(node.val);

        dfs(node.left, ans, targetSum, num + node.val);

        dfs(node.right, ans, targetSum, num + node.val);

        //每个节点最后都要移除

        ans.remove(ans.size() - 1);

    }

}

 

15、合并二叉树(节点值相加)

思路:递归

public class Solution {

    /**

     *

     * @param t1 TreeNode类

     * @param t2 TreeNode类

     * @return TreeNode类

     */

    public TreeNode mergeTrees (TreeNode t1, TreeNode t2) {

        if (t1 == null && t2 == null) return null;

        if (t1 == null || t2 == null) return t1 == null ? t2 : t1;

        // 此时 t1、t2 均不为 null

        // 合并节点的值

        t1.val = t1.val + t2.val;

        // 合并左子树

        t1.left = mergeTrees(t1.left, t2.left);

        // 合并右子树

        t1.right = mergeTrees(t1.right, t2.right);

        return t1;

    }

}

 

16、二叉树的镜像

思路:递归后交换返回的节点

public TreeNode Mirror (TreeNode pRoot) {

        if(pRoot == null) {

            return null;

        }

        if(pRoot.left == null && pRoot.right == null) {

            return pRoot;

        }

        TreeNode L = Mirror(pRoot.left);

        TreeNode R = Mirror(pRoot.right);

        pRoot.left = R;

        pRoot.right = L;

        return pRoot;

    }

 

17、判断是否对称(为镜像)

思路:递归辅助函数判断左右是否为空及其值/使用Deque双端队列进行层次遍历

方法1:递归

public class Solution {

    public boolean isSymmetric (TreeNode root) {

        if (root == null) return true;

        return recur(root.left, root.right);

    }

    // 递归辅助函数

    public boolean recur(TreeNode left, TreeNode right) {

        if (left == null && right == null) return true;

        else if (left != null && right == null) return false;

        else if (left == null && right != null) return false;

        else return left.val == right.val && recur(left.left, right.right) && recur(left.right, right.left);

    }

}

 

方法2:层次遍历-Deque

public boolean isSymmetric (TreeNode root) {

    if (root == null) return true;

    Deque<TreeNode> queue = new LinkedList<>();

    queue.addLast(root.left);

    queue.addLast(root.right);

    while (!queue.isEmpty()) {

        TreeNode left = queue.pollLast();

        TreeNode right = queue.pollLast();

        if (left == null && right == null) continue;

        if (left == null || right == null) return false;

        if (left.val != right.val) return false;     //队列需要添加4个元素

        queue.addFirst(left.left);

        queue.addFirst(right.right);

        queue.addFirst(left.right);

        queue.addFirst(right.left);

    }

 

    return true;

}

 

18、是否存在指定和的路径

思路:递归&sum-根的值

public class Solution {

    public boolean hasPathSum(TreeNode root, int sum) {

        if (root == null)

            return false;

 

        sum -= root.val;

        if (sum == 0 && root.left == null && root.right == null)

            return true;

 

        return hasPathSum(root.left, sum) || hasPathSum(root.right, sum);

    }

}

 

19、根到叶节点的所有路径和

思路:数字拼接改变节点的值&使用栈存节点/递归

方法1

private int val = 0;

    public int sumNumbers (TreeNode root) {

        // write code here

        if(root==null)

            return 0;

        //dfs(root,0);

//使用栈,将从根节点往下的值依次相加,直到左右子树均为空且栈空,则表示到达最底部。

        Stack<TreeNode> st = new Stack<>();

        st.push(root);

        while(!st.isEmpty()){

            TreeNode p = st.pop();

            if(p.left==null && p.right==null){

                val = val + p.val; //val计算路径和

            }else{

                if(p.left!=null){

                    p.left.val = p.val * 10 + p.left.val;

                    st.push(p.left);

                }

                if(p.right!=null){

                    p.right.val = p.val *10 + p.right.val;

                    st.push(p.right);

                }

            }

        }

        return val;

    }

 

方法2

import java.util.*;

/*

 * public class TreeNode {

 *   int val = 0;

 *   TreeNode left = null;

 *   TreeNode right = null;

 * }

 */

public class Solution {

    private int res = 0;

    /**

     *

     * @param root TreeNode类

     * @return int整型

     */

    public int sumNumbers (TreeNode root) {

        if(root==null){

            return 0;

        }

        process(root,0);

        return res;

    }

    private void process(TreeNode root,int agg){

        agg = agg*10 + root.val;

        if(root.left==null&&root.right==null){

            res = res + agg;

        }else{

            if(root.left!=null){

                process(root.left,agg);

            }

            if(root.right!=null){

                process(root.right,agg);

            }

        }

    } 

}

 

20、升序数组转平衡二叉树

思路:类似二分,选择中间元素作为根

public class Solution22 {

    public TreeNode sortedArrayToBST(int[] num) {

        if(num==null||num.length==0)

            return null;

        return sorted(num,0,num.length-1);

    }

     

    public TreeNode sorted(int[] num,int left,int right) {

         if(left>right)

             return null;

         int mid =(left+right+1)/2;

         int num1 =num[mid];

         TreeNode node = new TreeNode(num1);

         node.left =sorted(num,left,mid-1);

         node.right = sorted(num,mid+1,right);

         return node;

    }

}

 

21、判断是否为搜索二叉树

思路:回溯

import java.util.*;

 

/*

 * public class TreeNode {

 *   int val = 0;

 *   TreeNode left = null;

 *   TreeNode right = null;

 * }

 */

 

public class Solution {

    /**

     *

     * @param root TreeNode类 the root

     * @return bool布尔型一维数组

     */

     

    boolean searchFlag= true;

    boolean completeFlag = true;

    int num=Integer.MIN_VALUE;

    Stack<Integer> stack = new Stack<>(); 

     

    public boolean[] judgeIt (TreeNode root) {

        dfs(root,0);

        return new boolean[]{searchFlag, completeFlag};

    }

     

    public void dfs(TreeNode root, int len) {

        //如果两者为false,则开始剪枝

        if(!searchFlag && !completeFlag) return ;

        if(root==null){

            //判断是否是完全二叉树:

            //如果是完全二叉树,那么每个空子叶节点所在路径长度差值不得大于1,并且左子节点路径长度必须大于等于右子节点路径长度

            //当节点为空说明是一个空子叶节点,此时将该路径长度与前一个路径(上一个空子节点路径)的长度做比较,如果大于则不是完全二叉树

            if(stack.size()>=1 && stack.peek()<len) completeFlag=false;

            stack.add(len);

            return ;

        } 

         

        dfs(root.left, len+1);

        //判断是否是搜索二叉树:

        //如果是搜索二叉树,那么中序遍历的结果应该是递增关系。

        //如果此访问节点值小于上一个访问节点值,说明破坏了递增规律,则不是搜索二叉树。

        if(root.val>=num){

            num = root.val;

        }else {

            searchFlag=false;

        }

        dfs(root.right,len+1);

    }

}

 

22、二叉排序树第k/小节点

思路:中序遍历第k个节点

import java.util.*;

 

// 中序遍历

public class Solution {

    TreeNode KthNode(TreeNode pRoot, int k) {

        if(pRoot==null) return null;

        int count = 0;

        List<TreeNode> stack = new ArrayList<>();

        while(!stack.isEmpty() || pRoot!=null) {

            if(pRoot!=null) {// 先往左找

                stack.add(pRoot);

                pRoot = pRoot.left;

            }

            else {//找到最左,出栈

                pRoot = stack.remove(stack.size()-1);

                count++;

                if(count==k) return pRoot;

                pRoot = pRoot.right;

            }

        }

         

        return null;

    }

 

}

23、重建并输出右视图

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 求二叉树的右视图
     * @param xianxu int整型一维数组 先序遍历
     * @param zhongxu int整型一维数组 中序遍历
     * @return int整型一维数组
     */
    //思路:使用队列BFS层次遍历,当到达最后一个节点时加入res
    public int[] solve (int[] xianxu, int[] zhongxu) {
        List<Integer> res = new ArrayList<>();
        //先确定二叉树
        TreeNode root = reconstrution(xianxu, 0, xianxu.length - 1, zhongxu, 0, zhongxu.length - 1);
        //使用队列,对树进行层次遍历
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            int size = queue.size();
            for(int i = 0; i < size; i++) {
                if(i == size - 1) {
                    res.add(queue.peek().val);
                }
                TreeNode node = queue.poll();
                if(node.left != null) {
                    queue.offer(node.left);
                }
                if(node.right != null) {
                    queue.offer(node.right);
                }
            }
        }
        return res.stream().mapToInt(x -> x).toArray();
    }
    //递归,类似回溯:路径、选择列表、结束条件
    //但是回溯要移除选择,而递归无需移除选择
    public TreeNode reconstrution(int[] xianxu, int preStart, int preEnd, int[] zhongxu, int inStart, int inEnd) {
        if(preStart > preEnd || inStart > inEnd) {
            return null;
        }
        TreeNode root = new TreeNode(xianxu[preStart]);
        //找到中序的位置
        int i = 0;
        for(i = inStart; i <= inEnd; i++) {
            if(zhongxu[i] == xianxu[preStart]) {
                break;
            }
        }
        root.left = reconstrution(xianxu, preStart + 1, preStart + (i - inStart), zhongxu, inStart, i - 1);
        root.right = reconstrution(xianxu, preStart + (i - inStart) + 1, preEnd, zhongxu, i + 1, inEnd);
        return root;
    }
}

 

posted @ 2022-02-14 11:06  哥们要飞  阅读(44)  评论(0编辑  收藏  举报