给出节点数,然后找出所有可能的二叉树形状;
小目标
搞懂递归和动态规划
解题思路
解法一:递归法
我们从序列 1 …n 中取出数字 i,作为当前树的树根。于是,剩余 i - 1 个元素可用于左子树,n - i 个元素用于右子树;
不行,我感觉递归太难理解了;宣布失败
class Solution {
public:
vector<TreeNode*> generateTrees(int n) { // 直接存的就是 指向结构体类型的节点的指针地址
// 主要给的是节点数,然后给出所有的可能 二叉树形状
// 题意是理解了,但是短暂没有思路
if(n==0){
return {};
}
return solve(1,n);
}
private:
vector<TreeNode*> solve(int left, int right){
if (left > right)
return { nullptr };
vector<TreeNode*>res;
for (int i = left; i <= right; i++) {
vector<TreeNode*> lef_res = solve(left, i - 1);
vector<TreeNode*> rig_res = solve(i + 1, right);
for (int j = 0; j < lef_res.size(); j++) {
for (int k = 0; k < rig_res.size(); k++) {
TreeNode *node = new TreeNode(i);
node->left = lef_res[j];
node->right = rig_res[k];
res.push_back(node);
}
}
}
return res;
}
};
解法二:动态规划
95%以上的递归都可以用动态规划来改写;
对树的操作和指针理解很有帮助
lass Solution {
public:
TreeNode* gen(TreeNode* root,int shift){
if(root==nullptr) return nullptr;
TreeNode* back = new TreeNode(root->val + shift);
back->left = gen(root->left,shift);
back->right = gen(root->right,shift);
return back;
}
TreeNode* copy(TreeNode* root){
if(root==nullptr) return nullptr;
TreeNode* back = new TreeNode(root->val);
back->left = copy(root->left);
back->right = copy(root->right);
return back;
}
vector<TreeNode*> generateTrees(int n) {
vector<vector<TreeNode*>> dp(n+1);
if(n==0) return dp[0];
dp[0].push_back(nullptr);
dp[1].push_back(new TreeNode(1));
for(int i=2; i<=n ;i++){
for(int j=1;j<=i;j++){
TreeNode* temp = new TreeNode(j);
for(int k=0;k<dp[j-1].size();k++){ //连接左子树
temp->left = dp[j-1][k];
for(int z=0;z<dp[i-j].size();z++){
if(dp[i-j][z])
// cout << i-j <<dp[i-j][z]->val << endl;
temp->right = gen(dp[i-j][z],j);
TreeNode* push = copy(temp); //浅拷贝,若直接压入vector会有问题。
dp[i].push_back(push);
} //连接右子树
}
}
}
return dp[n];
}
};
注意多使用私有方法
class Solution {
public:
vector<TreeNode*> generateTrees(int n) {
vector<TreeNode*> dp;
if( n == 0 )
return dp;
dp.push_back(new TreeNode(1));
for( int i = 2; i <= n; i++ )
{
int size = dp.size();
for( int j = 0; j < size; j++ )
{
TreeNode *head = dp[j];
TreeNode *p = head;
while( p != NULL )
{
TreeNode *newHead = copyTree(head);
TreeNode *node = search(newHead,p->val);
TreeNode *nodeRight = node->right;
TreeNode *insertNode = new TreeNode(i);
node->right = insertNode;
insertNode->left = nodeRight;
dp.push_back(newHead);
p = p->right;
}
TreeNode *newHead = new TreeNode(i);
newHead->left = copyTree(head);
dp[j] = newHead;
}
}
return dp;
}
TreeNode* copyTree( TreeNode *node )
{
if( node == NULL)
return node;
TreeNode *newNode = new TreeNode(node->val);
newNode->left = copyTree(node->left);
newNode->right = copyTree(node->right);
return newNode;
}
TreeNode* search( TreeNode *node, int val )
{
if( node == NULL )
return node;
if( node->val > val )
return search(node->left,val);
else if( node->val < val )
return search(node->right,val);
else
return node;
}
};
** 看代码没有框架思路,看起来很头疼;还有不能只是眼看,还是得用手写出来,画出来**