随笔- 509  文章- 0  评论- 151  阅读- 22万 

Unique Binary Search Trees II

2014.2.10 02:54

Given n, generate all structurally unique BST's (binary search trees) that store values 1...n.

For example,
Given n = 3, your program should return all 5 unique BST's shown below.

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

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.

Solution:

  You know that the total number of binary search trees of n nodes is the nth Catalan number. But this time you have to build them all. It's hard labor, you know, both for the computer and for you.

  My solution is recursive, here is the description:

    1. for the sorted array a[1:n], pick some a[x] as the root. Every node a[i] will be the root node for some times. Thus this recursion has n branch.

    2. the left sub-array a[1:x-1] forms the left subtree, the right sub-array a[x+1:n] forms the right subtree.

    3. the left and right recursions return both result sets containing left subtrees and right subtrees.

    4. picking one from the left, and one from the right, together with the root node, you get a larger tree.

    5. put this larger tree in the result set. That's how a tree is built up.

  I've written a funtion copyTreeRecursive() to do a deep copy of trees, but later I realized that shallow copy of TreeNode pointers works just as fine, and would save a lot of allocated memory. If you're interested, please view the commented code segment below and find out why.

  Total time and space complexities are both O(n!) scale, as the nth Catalan number is C(2*n, n) / (n+ 1).

  The time and space usage of this algorithm is explosive, so it's quite easy to get a "Stackoverflow" from this program. You better expect n to be under 10, if you're waiting to see the result.

Accepted code:

复制代码
  1 // 1WA, 1AC, very good~
  2 // #define MY_MAIN
  3 #include <cstdio>
  4 #include <vector>
  5 using namespace std;
  6 /**
  7  * Definition for binary tree
  8  * struct TreeNode {
  9  *     int val;
 10  *     TreeNode *left;
 11  *     TreeNode *right;
 12  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 13  * };
 14  */
 15 
 16 #ifdef MY_MAIN
 17 struct TreeNode {
 18     int val;
 19     TreeNode *left;
 20     TreeNode *right;
 21     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 22 };
 23 #endif
 24 class Solution {
 25 public:
 26     vector<TreeNode *> generateTrees(int n) {
 27         int i;
 28         vector<int> num;
 29         vector<TreeNode *> result;
 30         
 31         result.clear();
 32         if (n == 0) {
 33             // 1WA here, you should return an empty tree when n=0.
 34             result.push_back(NULL);
 35             return result;
 36         }
 37         
 38         for (i = 1; i <= n; ++i) {
 39             num.push_back(i);
 40         }
 41         result = generateTreeRecursive(num);
 42         return result;
 43     }
 44 private:
 45     vector<TreeNode *> generateTreeRecursive(vector<int> num) {
 46         vector<TreeNode *> res;
 47         TreeNode *root_ptr;
 48         
 49         res.clear();
 50         if (num.size() == 0) {
 51             res.push_back(NULL);
 52             return res;
 53         } else if (num.size() == 1) {
 54             root_ptr = new TreeNode(num[0]);
 55             res.push_back(root_ptr);
 56             return res;
 57         }
 58         
 59         vector<int> vleft, vright;
 60         vector<TreeNode *> res_left, res_right;
 61         int count_left, count_right;
 62         int i, j, k;
 63         
 64         for (i = 0; i < (int)num.size(); ++i) {
 65             vleft.clear();
 66             vright.clear();
 67             res_left.clear();
 68             res_right.clear();
 69             // the left subtree
 70             for (j = 0; j < i; ++j) {
 71                 vleft.push_back(num[j]);
 72             }
 73             // the right subtree
 74             for (j = i + 1; j < (int)num.size(); ++j) {
 75                 vright.push_back(num[j]);
 76             }
 77             res_left = generateTreeRecursive(vleft);
 78             res_right = generateTreeRecursive(vright);
 79             count_left = (int)res_left.size();
 80             count_right = (int)res_right.size();
 81             for (j = 0; j < count_left; ++j) {
 82                 for (k = 0; k < count_right; ++k) {
 83                     root_ptr = new TreeNode(num[i]);
 84                     // root_ptr->left = copyTreeRecursive(res_left[j]);
 85                     // root_ptr->right = copyTreeRecursive(res_right[k]);
 86                     root_ptr->left = res_left[j];
 87                     root_ptr->right = res_right[k];
 88                     res.push_back(root_ptr);
 89                 }
 90             }
 91         }
 92         
 93         return res;
 94     }
 95 
 96     TreeNode *copyTreeRecursive(const TreeNode *root)
 97     {
 98         TreeNode *new_root;
 99         
100         if (root == NULL) {
101             return NULL;
102         }
103         new_root = new TreeNode(root->val);
104         if (root->left != NULL) {
105             new_root->left = copyTreeRecursive(root->left);
106         }
107         if (root->right != NULL) {
108             new_root->right = copyTreeRecursive(root->right);
109         }
110 
111         return new_root;
112     }
113 };
114 
115 #ifdef MY_MAIN
116 void preorderTraversal(const TreeNode *root, vector<int> &result)
117 {
118     if (root == NULL) {
119         result.push_back(0);
120     }
121     result.push_back(root->val);
122     if (root->left != NULL) {
123         preorderTraversal(root->left, result);
124     } else {
125         result.push_back(0);
126     }
127     if (root->right != NULL) {
128         preorderTraversal(root->right, result);
129     } else {
130         result.push_back(0);
131     }
132 }
133 
134 int main()
135 {
136     int n;
137     Solution solution;
138     vector<int> traversal_result;
139     vector<TreeNode *> trees;
140     int i, j;
141     
142     while (scanf("%d", &n) == 1) {
143         if (n < 0) {
144             continue;
145         }
146         trees = solution.generateTrees(n);
147         for (i = 0; i < (int)trees.size(); ++i) {
148             traversal_result.clear();
149             preorderTraversal(trees[i], traversal_result);
150             for (j = 0; j < (int)traversal_result.size(); ++j) {
151                 if (j == 0) {
152                     printf("%d", traversal_result[j]);
153                 } else {
154                     printf(" %d", traversal_result[j]);
155                 }
156             }
157             printf("\n");
158         }
159         printf("Catalan[%d] = %d\n", n, (int)trees.size());
160         printf("\n");
161     }
162     
163     return 0;
164 }
165 #endif
复制代码

 

 posted on   zhuli19901106  阅读(163)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示