wpcockroach

导航

LeetCode之Unique Binry Search Trees

4月份很快就过半了,最近都在看WPF,有点落伍了...本来想写一点读书笔记的,还没想好要怎么写。所以为了能够达到每月一篇博客的目标,今天先说一个LeetCode上的面试题:Unique Binary Search Trees

题目简单翻译过来就是说:

给定n个不同节点,问:可以构造出多少种异构的二叉搜索树。比方说n=3时有5种:

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

一般来说,遇到这种问题多半是找规律,总结出数学公式然后解决之。找规律前,首先要看我们有哪些可以利用的条件。

这里可用的条件很有限但也很明确:二叉搜索树。也就是其任意一部分二叉树都满足左子树节点都小于(或者大于)根节点;右子树节点都大于(或者小于)根节点。

我们已经有了n=3的结果,那么来看看n=4时的情况。我们知道,任何一个节点都可以成为一个根节点,那么:

  • 如果以1为树根,那么剩下的三个节点都分布在该树的右子树上;
  • 如果以2为树根,那么节点1必然是其左子树上的唯一节点,而3、4只可能在其优节点上;
  • 如果以3为树根,那么节点2、3在其左子树上,而节点4是其右子树上的唯一节点;
  • 如果以4为树根,那么甚于节点都在其左子树上;

这个简单的分析过程很快就将规律呈现了出来!!

对于n=4的情况,其异构结果就是各种独立情况下,左子树和右子树异构方式的排列数之和。用公式表示就是:f(4) = f(0) * f(3) + f(1) * f(2) + f(2) * f(1) + f(3) * f(0)。整一个典型的递归实现。唯一需要考虑的点就是你需要缓存一下中间数据,因为f(2)和f(3)分别被调用了2次。

 1 class Solution {
 2 public:
 3     int numTrees(int n) {
 4         static vector<int> cached(1, 1);
 5         if (n > cached.size())
 6         {
 7             cached.resize(n, 0);
 8         }
 9 
10         if (0 == n)
11         {
12             return 1;
13         }
14         
15         if (cached[n - 1] != 0)
16         {
17             return cached[n - 1];
18         }
19         else
20         {
21             for (int i = 0; i < n; ++i)
22             {
23                 cached[n - 1] += numTrees(i) * numTrees(n - i - 1);
24             }
25             
26             return cached[n - 1];
27         }
28     }
29 };

顺带因为打算以后要有Python,所以附带上Python的代码。刚开始学着写Python,写着有点难过...(有没有更好的写法?)

 1 class Solution:
 2     # @return an integer
 3     def numTrees(self, n):
 4         if 0 == n:
 5             return 1
 6 
 7         cached = [1]
 8         if n > len(cached):
 9             result = 0;
10             for i in range(n):
11                 index = n - i - 1
12                 
13                 left_part_result = self.numTrees(i)
14                 right_part_result = self.numTrees(index)
15                 
16                 result += left_part_result * right_part_result
17 
18                 if index == len(cached):
19                     cached[len(cached):] = [right_part_result]
20 
21             cached[len(cached):] = [result]
22             
23             return result
24         else:
25             return cached[n - 1];

这题目的背景是一个称之为Catalan Number的数。也可以参看百度百科。通过了解Catalan Number,我们会发现他的诸多应用。比方说凸多边形的最优三角划分就是这个问题的拓展。

posted on 2014-04-18 01:04  wpcockroach  阅读(509)  评论(0编辑  收藏  举报