zoukankan      html  css  js  c++  java
  • LeetCode解题报告—— Unique Binary Search Trees & Binary Tree Level Order Traversal & Binary Tree Zigzag Level Order Traversal

    1. Unique Binary Search Trees

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n?

    For example,
    Given n = 3, there are a total of 5 unique BST's.

       1         3     3      2      1
               /     /      /       
         3     2     1      1   3      2
        /     /                        
       2     1         2                 3

    思路:和 Unique Binary Search Trees II 不同,只是需要计算总共的数量,可以利用dp来解决。从1~n选择i作为root,那么1到i-1构成其左子树,i+1到n构成其右子树。作如下定义,

    G(n): the number of unique BST for a sequence of length n.

    F(i, n), 1 <= i <= n: the number of unique BST, where the number i is the root of BST, and the sequence ranges from 1 to n.

    从以上定义,可得

    G(n) = F(1, n) + F(2, n) + ... + F(n, n). 

    并且G(0)=1, G(1)=1. 即空树和只有一个节点的情况。对于dp,要解决的问题是能分成若干个相同的子问题,并且计算有重复的情形。以 [1, 2, 3, 4, 5, 6, 7] 为例子,要计算的是G(7),如果以3为根,要计算F(3,7)。[1,2]构成左子树,[4,5,6,7]构成右子树。对于[1,2],其实就是计算G(2),而对于[4,5,6,7],可以将其等同于计算G(4),即F(3,7) = G(2) * G(4)。因此有下面等式

    F(i, n) = G(i-1) * G(n-i)	1 <= i <= n 

    结合上面的公式可得出

    G(n) = G(0) * G(n-1) + G(1) * G(n-2) + … + G(n-1) * G(0) 

    所以从低向上计算,即从G(0),G(1)开始一直计算出G(n)即可。

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

     

    2. Binary Tree Level Order Traversal

    Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).

    For example:
    Given binary tree [3,9,20,null,null,15,7],

        3
       / 
      9  20
        /  
       15   7

    return its level order traversal as:

    [
      [3],
      [9,20],
      [15,7]
    ]

    思路:层次遍历二叉树,没什么好说的,主要是掌握队列的用法。

    public class Solution {
        public List<List<Integer>> levelOrder(TreeNode root) {
            Queue<TreeNode> queue = new LinkedList<TreeNode>();
            List<List<Integer>> wrapList = new LinkedList<List<Integer>>();
            
            if(root == null) return wrapList;
            
            queue.offer(root);
            while(!queue.isEmpty()){
                int levelNum = queue.size();
                List<Integer> subList = new LinkedList<Integer>();
                for(int i=0; i<levelNum; i++) {
                    if(queue.peek().left != null) queue.offer(queue.peek().left);
                    if(queue.peek().right != null) queue.offer(queue.peek().right);
                    subList.add(queue.poll().val);
                }
                wrapList.add(subList);
            }
            return wrapList;
        }
    }

    关于java中队列的用法可以参考这篇博文:https://www.cnblogs.com/samjustin/p/5785078.html

    3. Binary Tree Zigzag Level Order Traversal

    Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).

    For example:
    Given binary tree [3,9,20,null,null,15,7],

        3
       / 
      9  20
        /  
       15   7

    return its zigzag level order traversal as:

    [
      [3],
      [20,9],
      [15,7]
    ]

    思路:基于上个题目的改进,本来以为改下上题的代码,判断每层层号的奇偶,再逆置,这样做的确可以解题,但是太过繁琐。还是参考了下答案。使用递归思路求解,对于层次遍历来说,每一层的遍历,都是逻辑相同,参数不同。关键是怎么在这个递归中寻找终止条件,以及一层层向下递归时固定的参数变化规律。

    public class Solution {
        public List<List<Integer>> zigzagLevelOrder(TreeNode root) 
        {
            List<List<Integer>> sol = new ArrayList<>();
            travel(root, sol, 0);
            return sol;
        }
        
        private void travel(TreeNode curr, List<List<Integer>> sol, int level)
        {
            if(curr == null) return; // 没有下层了,递归就往上层返回
            
            if(sol.size() <= level) // 当递归发现还有下层的话,就为这层新建个List,并加入到sol中
            {
                List<Integer> newLevel = new LinkedList<>();
                sol.add(newLevel);
            }
            
            List<Integer> collection  = sol.get(level);  // 这里根据层号取List,所以即使两个从上到下的递归路径不同,但是相同层取到的还是相同的List
            if(level % 2 == 0) collection.add(curr.val);  // 根据层号奇偶判断这层的List在加入元素时是正序还是逆序
            else collection.add(0, curr.val);  // 学到了
            
            travel(curr.left, sol, level + 1);   // 往下层左子树递归
            travel(curr.right, sol, level + 1);  // 往下层右子树递归
        }
    }

    上面的基本递归思路是利用到DFS,整个过程每层的元素不是一层层遍历完的,而是每递归到一个底层,从这层往上的所有层所对应的List都添加了在这层遍历到的元素,并且根据层号的奇偶决定是往后插还是往前插,这样来实现顺序和倒序的遍历,这也为层次遍历提供了一种递归实现的思路。注意上面的 collection.add(0, curr.val) 方法,将值插入指定位置,原来位置上的值会依次往后移。

  • 相关阅读:
    【NOIP2007】守望者的逃离
    20200321(ABC)题解 by 马鸿儒 孙晨曦
    20200320(ABC)题解 by 王一帆
    20200319(ABC)题解 by 王一帆 梁延杰 丁智辰
    20200314(ABC)题解 by 董国梁 蒋丽君 章思航
    20200309(ABC)题解 by 梁延杰
    20200307(DEF)题解 by 孙晨曦
    20200306(ABC)题解 by 孙晨曦
    20200305(DEF)题解 by 孙晨曦
    20200303(ABC)题解 by 王锐,董国梁
  • 原文地址:https://www.cnblogs.com/f91og/p/8684066.html
Copyright © 2011-2022 走看看