leetcode之二叉树

目录

1.binary-tree-preorder-traversal

2.binary-tree-postorder-traversal

3.binary-tree-inorder-traversal

4.binary-tree-level-order-traversal

5.binary-tree-zigzag-level-order-traversal

6.binary-tree-level-order-traversal-ii

7.construct-binary-tree-from-preorder-and-inorder-traversal

8.construct-binary-tree-from-inorder-and-postorder-traversal

9. Minimum Depth of Binary Tree

10.maximum-depth-of-binary-tree

11.balanced-binary-tree

12.sum-root-to-leaf-numbers

13.path-sum

14.path-sum-ii

15.binary-tree-maximum-path-sum

16.symmetric-tree

17.same-tree

18.populating-next-right-pointers-in-each-node

19.populating-next-right-pointers-in-each-node-ii

20.unique-binary-search-trees

21.unique-binary-search-trees-ii

22.recover-binary-search-tree

23.validate-binary-search-tree


1.binary-tree-preorder-traversal

题目:求给定二叉树的前序遍历

分析:迭代实现,前序遍历根结点,先后将右、左子树压入栈,这样的访问顺序为“中左右”,即前序遍历。

    public ArrayList<Integer> preorderTraversal(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        if(root == null)
            return list;
        Stack<TreeNode> stack = new Stack();
        stack.push(root);
        while(!stack.empty()){
            TreeNode node = stack.pop();
            if(node.right != null)
                stack.push(node.right);
            if(node.left != null)
                stack.push(node.left);
            list.add(node.val);
        }
        return list;
    }

2.binary-tree-postorder-traversal

题目:求给定二叉树的后序遍历

分析:迭代实现,前序遍历根结点,先后将左右子树压入栈,这样的访问顺序为“中右左”,最后再reverse即可。reverse:  list.add(0,node.val);

   public ArrayList<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer> list = new ArrayList();
        if(root == null)
            return list;
        Stack<TreeNode> s = new Stack();
        s.push(root);
        while(!s.empty()){
            TreeNode node = s.pop();
            if(node.left != null)
                s.push(node.left);
            if(node.right != null)
                s.push(node.right);
            list.add(0,node.val);//因为出栈顺序为“根右左”,所以需要每次将元素插入list开头
        }
        return list;
    }

3.binary-tree-inorder-traversal

题目:给出一棵二叉树,返回这棵树的中序遍历。例如:给出的二叉树为{1,#,2,3},返回[1,3,2].

分析:用栈来实现二叉树的中序遍历

   public ArrayList<Integer> inorderTraversal(TreeNode root) {
        ArrayList<Integer> list = new ArrayList();
        if(root == null)
            return list;
        Stack<TreeNode> stack = new Stack();
        TreeNode cur = root;
        while(! stack.empty() || cur != null){
            if(cur != null){
                stack.push(cur);
                cur = cur.left;
            }
            else{
                cur = stack.pop();
                list.add(cur.val);
                cur = cur.right;
            }
        }
        return list;
    }

4.binary-tree-level-order-traversal

题目:给定一个二叉树,返回该二叉树层序遍历的结果。例如:给定的二叉树{3,9,20,#,#,15,7},该二叉树层序遍历的结果是[↵ [3],↵ [9,20],↵ [15,7]↵]

分析:见剑指offer面试题32-1https://blog.csdn.net/Nibaby9/article/details/104124413

5.binary-tree-zigzag-level-order-traversal

题目:给定一个二叉树,返回该二叉树的之字形层序遍历,(从左向右,下一层从右向左,一直这样交替)。例如:给定的二叉树{3,9,20,#,#,15,7}, 该二叉树之字形层序遍历的结果是[↵ [3],↵ [20,9],↵ [15,7]↵]

分析:见剑指offer面试题32-2https://blog.csdn.net/Nibaby9/article/details/104124413

6.binary-tree-level-order-traversal-ii

题目:给定一个二叉树,返回该二叉树由底层到顶层的层序遍历,(从左向右,从叶子节点到根节点,一层一层的遍历)例如:给定的二叉树是{3,9,20,#,#,15,7},该二叉树由底层到顶层层序遍历的结果是[↵ [15,7]↵ [9,20],↵ [3],↵]

分析:还是按原来的方法进行层序遍历,只不过把每层遍历的结果都加到结果集的最前面。

   public ArrayList<ArrayList<Integer>> levelOrderBottom(TreeNode root) {
        ArrayList<ArrayList<Integer>> result = new ArrayList();
        if(root == null)
            return result;
        ArrayList<Integer> list = new ArrayList();
        LinkedList<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(! queue.isEmpty()){
            list.clear();
            int size = queue.size();
            while(size > 0){
                TreeNode cur = queue.poll();
                size--;
                list.add(cur.val);
                if(cur.left != null)
                    queue.offer(cur.left);
                if(cur.right != null)
                    queue.offer(cur.right);
            }
            result.add(0,new ArrayList(list));
        }
        return result;
    }

7.construct-binary-tree-from-preorder-and-inorder-traversal

题目:给出一棵树的前序遍历和中序遍历,请构造这颗二叉树。注意:可以假设树中不存在重复的节点

分析:见剑指offer面试题7https://blog.csdn.net/Nibaby9/article/details/104124413

8.construct-binary-tree-from-inorder-and-postorder-traversal

题目:给出一棵树的中序遍历和后序遍历,请构造这颗二叉树。注意:保证给出的树中不存在重复的节点

分析:同中序遍历和先序遍历的构造!!

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if(inorder == null || postorder == null || inorder.length != postorder.length || inorder.length == 0)
            return null;
        return build(inorder,postorder,0,inorder.length-1,0,postorder.length-1);
    }

    private TreeNode build(int[] inorder, int[] postorder, int instart, int inend,int pstart, int pend) {
        if(instart > inend || pstart > pend)
            return null;
        TreeNode root = new TreeNode(postorder[pend]);
        int size = 0;
        for(int i = instart;i <= inend;i++){
            if(postorder[pend] == inorder[i])
                break;
            size++;
        }
        root.left = build(inorder,postorder,instart,instart+size-1,pstart,pstart+size-1);
        root.right = build(inorder,postorder,instart+size+1,inend,pstart+size,pend-1);
        return root;
    }

9. Minimum Depth of Binary Tree

题目:求给定二叉树的最小深度。最小深度是指树的根结点到最近叶子结点的最短路径上结点的数量。

分析:递归实现,注意分析没有左子树和右子树的情况      f(x) =  1  + min{ f(left),f(right) }

   public int run(TreeNode root) {
         if(root == null){
            return 0;
        }
        int left = run(root.left);
        int right = run(root.right);
        if(left == 0 || right == 0)
            return left + right + 1;
        return 1 + (left > right ? right :left);
    }

10.maximum-depth-of-binary-tree

题目:求给定二叉树的最大深度,最大深度是指树的根结点到最远叶子结点的最长路径上结点的数量。

分析:见剑指offer面试题55https://blog.csdn.net/Nibaby9/article/details/104124413

11.balanced-binary-tree

题目:判断给定的二叉树是否是平衡的。

分析:见剑指offer面试题55拓展https://blog.csdn.net/Nibaby9/article/details/104124413

12.sum-root-to-leaf-numbers

题目:给定一个仅包含数字0-9的二叉树,每一条从根节点到叶子节点的路径都可以用一个数字表示。例如根节点到叶子节点的一条路径是1->2->3,那么这条路径就用123来代替。找出根节点到叶子节点的所有路径表示的数字之和。例如: 1↵ / ↵ 2 3;根节点到叶子节点的路径1->2用数字12代替,根节点到叶子节点的路径1->3用数字13代替,所以答案为12+13=25。

分析:主要在于参数的设计,记根结点以上的和为sum = sum*10+root.val;最后结果为左子树的和加右子树的和。

    public int sumNumbers(TreeNode root) {
        return sumUtil(root,0);
    }

    private int sumUtil(TreeNode root,int sum) {
        if(root == null)
            return 0;
        sum = sum * 10 + root.val;
        if(root.left == null && root.right == null)
            return sum;
        return sumUtil(root.left,sum) + sumUtil(root.right,sum);
    }

13.path-sum

题目:给定一个二叉树和一个值sum,判断是否有从根节点到叶子节点的节点值之和等于sum的路径

分析:递归求解,hasPathSum(root.left,sum - root.val)  ||  hasPathSum(root.right,sum - root.val)

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

14.path-sum-ii

题目:给定一个二叉树和一个值sum,请找出所有的根节点到叶子节点的节点值之和等于sum的路径

           例如:给出如下的二叉树,sum=22, 5↵ / ↵ 4 8↵ / / ↵ 11 13 4↵ / / ↵ 7 2 5 1,返回[↵ [5,4,11,2],↵ [5,8,4,5]↵]↵

分析:递归求解,主要还是在于参数的设置

public ArrayList<ArrayList<Integer>> pathSum(TreeNode root, int sum) {
        ArrayList<ArrayList<Integer>> result = new ArrayList();
        if(root == null)
            return result;
        ArrayList<Integer> tmp = new ArrayList();
        pathSumUtil(root,sum,result,tmp);
        return result;
    }

    private void pathSumUtil(TreeNode root, int sum, ArrayList<ArrayList<Integer>> result, ArrayList<Integer> tmp) {
        tmp.add(root.val);//试探
        if(root.val == sum && root.left == null && root.right == null)
            result.add(new ArrayList(tmp));
        if(root.left != null)
            pathSumUtil(root.left,sum - root.val,result,tmp);
        if(root.right != null)
            pathSumUtil(root.right,sum - root.val,result,tmp);
        tmp.remove(tmp.size() - 1);//回溯!!!
    }

15.binary-tree-maximum-path-sum

题目:给定一个二叉树,请计算节点值之和最大的路径的节点值之和是多少。这个路径的开始节点和结束节点可以是二叉树中的任意节点。例如:给出以下的二叉树, 1↵ / ↵ 2 3,返回的结果为6

分析:需计算两个最大值,一个是当前节点下最大路径和,另一个是如果要连接父节点时最大的路径和。用前者更新全局最大量,用后者返回递归值就行了。

  public class Solution {
    int max = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        sumUtil(root);
        return max;
    }

    private int sumUtil(TreeNode root) {
        if(root == null)
            return 0;
        int left = Math.max(0, sumUtil(root.left));
        int right = Math.max(0, sumUtil(root.right));
        max = Math.max(max, root.val + left + right);
        return Math.max(left, right) + root.val;
    }
}

16.symmetric-tree

题目:给定一棵二叉树,判断琪是否是自身的镜像(即:是否对称)

分析:见剑指offer面试题28https://blog.csdn.net/Nibaby9/article/details/104124413

17.same-tree

题目:给出两个二叉树,请写出一个判断两个二叉树是否相等的函数。判断两个二叉树相等的条件是:两个二叉树的结构相同,并且相同的节点上具有相同的值。

分析:easy!递归判断左右子树是否相同即可。

   public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p == null && q == null)
            return true;
        if(p == null || q == null)
            return false;
        if(p.val != q.val)
            return false;
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }

18.populating-next-right-pointers-in-each-node

题目:给定一棵满二叉树 struct TreeLinkNode {TreeLinkNode *left;TreeLinkNode *right;TreeLinkNode *next; }填充所有节点的next指针,指向它右兄弟节点。如果没有右兄弟节点,则应该将next指针设置为NULL。初始时,所有的next指针都为NULL

分析:由于给定的树为满二叉树,所以对于一个结点:它的左子树的next为它的右子树;它的右子树的next为它的next的左子树

public void connect(TreeLinkNode root) {
        if(root == null)
            return;
        if(root.left != null && root.right != null)
            root.left.next = root.right;
        if(root.next != null && root.right != null)
            root.right.next = root.next.left;
        connect(root.left);
        connect(root.right);
 }

19.populating-next-right-pointers-in-each-node-ii

题目:继续思考"Populating Next Right Pointers in Each Node".这道题。如果给定的树可以是任意的二叉树呢?你之前的给出的算法还有效吗?注意:你只能使用常量的额外内存空间

分析:层次遍历,但遍历前先模拟新建立的每层的第一个结点,以方便后面遍历

   public void connect(TreeLinkNode root) {
        while(root != null){
            TreeLinkNode firstNode = new TreeLinkNode(0);
            TreeLinkNode cur = firstNode;
            while(root != null){
                if(root.left != null){
                    cur.next = root.left;
                    cur = cur.next;
                }
                if(root.right != null){
                    cur.next = root.right;
                    cur = cur.next;
                }
                root = root.next;
            }
            root = firstNode.next;
        }
    }

20.unique-binary-search-trees

题目:给定一个值n,能构建出多少不同的值包含1...n的二叉搜索树(BST)?例如:给定 n = 3, 有五种不同的二叉搜索树

分析:动态规划。一维数组dp[i]表示1...i数字能组成多少种二叉搜索树,dp[0] = 1;dp[1] = 1;dp[n] = sum{dp[j] * dp[n-j-1]},0<j<n

   public int numTrees(int n) {
        if(n < 0)
            return 0;
        int []dp = new int[n+1];
        dp[0] = 1;
        dp[1] = 1;
        for(int i = 2;i <= n;i++){
            for(int j =0;j < i;j++){
                dp[i] += dp[j] * dp[i-j-1];
            }
        }
        return dp[n];
    }

21.unique-binary-search-trees-ii

题目:给定一个值n,请生成所有的存储值1...n.的二叉搜索树(BST)的结构例如:给定n=3,你的程序应该给出五种不同的二叉搜索树

分析:用递归求出以i为根结点的所有左子树和右子树,然后再将所有左子树和右子树相互配对。

    public ArrayList<TreeNode> generateTrees(int n) {
        return generateTreesUtil(1,n);
    }

    private ArrayList<TreeNode> generateTreesUtil(int low, int high) {
        ArrayList<TreeNode> result = new ArrayList();
        if (low > high) {
            result.add(null);
            return result;
        }
        for(int i = low;i <= high;i++){//以i为根结点生成树
            ArrayList<TreeNode> left = generateTreesUtil(low,i-1);
            ArrayList<TreeNode> right = generateTreesUtil(i+1,high);
            for(int j = 0;j < left.size();j++){
                for(int k = 0;k < right.size();j++){
                    TreeNode root = new TreeNode(i);
                    root.left = left.get(j);
                    root.right = right.get(k);
                    result.add(root);
                }
            }
        }
        return result;
    }

22.recover-binary-search-tree

题目:二叉搜索树(BST)中的两个节点被错误地交换了,请在不改变树的结构的情况下恢复这棵树。备注:用O(n)的空间解决这个问题的方法太暴力了,你能设计一个常数级空间复杂度的算法么?

分析:利用二叉搜索树中序遍历有序性,对于一组有序的数,两个数被错误调换,如1  2  10  8  9  4  11 12,第一个错误数是第一次出现pre>cur中的pre,第二个错误数是最后一次出现pre>cur中的cur.

   public void recoverTree(TreeNode root) {
        TreeNode first = null;
        TreeNode second = null;
        TreeNode pre = null;
        if(root == null)
            return;
        Stack<TreeNode> s = new Stack();
        TreeNode cur = root;
        while(!s.empty() || cur != null){
            if(cur != null){
                s.push(cur);
                cur = cur.left;
            }
            else{
                cur = s.pop();
                if(pre != null){
                    if(pre.val > cur.val) {
                        if (first == null)
                            first = pre;
                        second = cur;
                    }
                }
                pre = cur;
                cur = cur.right;
            }
        }
        if(first != null && second != null){
            int temp = first.val;
            first.val = second.val;
            second.val = temp;
        }
    }

23.validate-binary-search-tree

题目:判断给出的二叉树是否是一个二叉搜索树(BST)

分析:利用二叉搜索树中序遍历有序性,注意二叉搜索树满足左子树 < 根结点 < 右子树,没有等号,[1,1]不是BST

  public boolean isValidBST(TreeNode root) {
        if(root == null)
            return true;
        TreeNode pre = null;
        Stack<TreeNode> s = new Stack();
        TreeNode cur = root;
        while(!s.empty() || cur != null){
            if(cur != null){
                s.push(cur);
                cur = cur.left;
            }
            else{
                cur = s.pop();
                if(pre != null){
                    if(pre.val >= cur.val)
                        return false;
                }
                pre = cur;
                cur = cur.right;
            }
        }
        return true;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值