-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path0095-Unique_Binary_Search_Trees_II.cpp
More file actions
153 lines (138 loc) · 3.64 KB
/
0095-Unique_Binary_Search_Trees_II.cpp
File metadata and controls
153 lines (138 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*******************************************************************************
* 0095-Unique_Binary_Search_Trees_II.cpp
* Billy.Ljm
* 05 August 2023
*
* =======
* Problem
* =======
* https://leetcode.com/problems/unique-binary-search-trees-ii/
*
* Given an integer n, return all the structurally unique BST's (binary search
* trees), which has exactly n nodes of unique values from 1 to n. Return the
* answer in any order.
*
* ===========
* My Approach
* ===========
* To construct the binary tree, we have to create a root node, then append
* a left subtree with k nodes and right subtree with n-1-k nodes to it. Thus,
* we can generate the tree with dynamic programming, generating all trees with
* increasing number of nodes.
*
* This has a time complexity of O(n*G(n)), and a space complexity of
* O(\sum_{k=1}^n k*G(k)), where n is the number of nodes and G(n) is the
* Catalan number.
******************************************************************************/
#include <iostream>
#include <vector>
using namespace std;
/**
* Definition for a binary tree node.
*/
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};
/**
* Pre-Order traversal of binary tree, printing out the node values
*/
void preorderTraversal(TreeNode* node, std::ostream& os) {
if (node == nullptr) {
os << "null,";
}
else if (node->left == nullptr && node->right == nullptr) {
os << node->val << ",";
}
else {
os << node->val << ",";
preorderTraversal(node->left, os);
preorderTraversal(node->right, os);
}
}
/**
* << operator for binary tree nodes
*/
std::ostream& operator<<(std::ostream& os, TreeNode* root) {
os << "[";
preorderTraversal(root, os);
os << "\b]";
return os;
}
/**
* << operator for vectors
*/
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
os << "[";
for (int i = 0; i < v.size(); i++) {
os << v[i] << ",";
}
os << "\b]";
return os;
}
/**
* Solution
*/
class Solution {
private:
/**
* Clones a tree, numbering nodes in preorder, starting form offset
*
* @param root root of binary tree to copy
* @param offset number to offset node values by
* @return root of copied binary tree
*/
TreeNode* cloneTree(TreeNode* root, int offset) {
if (root == nullptr) return nullptr;
else return new TreeNode(root->val + offset,
cloneTree(root->left, offset), cloneTree(root->right, offset));
}
public:
/**
* Generates all structurally-distinct trees with n nodes
*
* @param n number of nodes in trees
* @return vector of all structurally-distinct trees
*/
vector<TreeNode*> generateTrees(int n) {
vector<vector<TreeNode*>> dp(n + 1);
// base case
dp[0] = { nullptr };
// general case
for (int i = 1; i <= n; i++) { // total number of nodes
for (int k = 0; k < i; k++) { // number of nodes in left subtree
for (TreeNode* leftsubtree : dp[k]) {
for (TreeNode* rightsubtree : dp[i - 1 - k]) {
// LeetCode apparently wants this specific node numbering
dp[i].push_back(new TreeNode(k + 1,
cloneTree(leftsubtree, 0),
cloneTree(rightsubtree, k+1)));
}
}
}
}
// return result
return dp[n];
}
};
/**
* Test cases
*/
int main(void) {
Solution sol;
int n;
// test case 1
n = 3;
std::cout << "generateTrees(" << n << ") = ";
std::cout << sol.generateTrees(n) << std::endl;
// test case 2
n = 1;
std::cout << "generateTrees(" << n << ") = ";
std::cout << sol.generateTrees(n) << std::endl;
return 0;
}