题目: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
思路:动态规划
本题目思路是动态规划。
本质上来讲我任选一个节点做根节点,那么我之前的节点都是保存的,我可以直接查表,而之后的dp[i-j]的呢,实际上,只需要把所有后面那部分+j即可。
比如说i=2,j=1,2,假设从1开始 k: 0 – 0 , w: 0 – 0 ,左右各插入一个节点.然后j=2,此时dp[i]又push了2进去。k: 0 – 0 , w: 0 – 0,左边插入一个节点。
也就是说i=2的时候,dp[2]里面保存了前面节点为1 和 为2的树。
假如i=1,dp[1]=1;
想一想:dp[2] 有1,2 其中dp[2][0]节点是1,左指向空,右指向2,dp[2][1]节点是2,左指向1,右指向空。
假如i=3,此时存入数字,dp[3]存入1 2 3。对于dp[3][0]来说,存入两个1,一个2,两个3
j=1:k: 0 – 0 , w: 0 – 1;两个1,左边不能放,dp[2]中存在1,2,右边添加节点1+1,和节点2+1.
j=2:k: 0 – 0 , w: 0 – 0;一个2
j=3:k: 0 – 1 , w: 0 – 0;两个3.。。。。。以此类推
每一个dp[i]里面存放了许多的j,而这些j一共有(i-1)*(i-j)个,而这些dp[i]都是指向左右节点。
代码
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution1 { public: vector<TreeNode*> generateTrees(int n) { vector<vector<TreeNode *> >dp(n+1); if(n<1){ dp[0].push_back(NULL); return dp[0]; } dp[0].push_back(NULL);dp[1].push_back(new TreeNode(1));//数字1没有其他节点 for(int i=2;i<=n;i++){ for(int j=1;j<=i;j++){//单独空的节点不考虑了,所以从1开始 for(int k=0;k<dp[j-1].size();k++){ for(int w=0;w<dp[i-j].size();w++){ //dp[i] push 的次数就是k*w的结果,所以每次都是push i一次 //然后他的back的left指向dp[j]的 dp[i].push_back(new TreeNode(j)); dp[i].back()->left=dp[j-1][k]; traverse_add_copy(dp[i-j][w],dp[i].back()->right,j); } } } } return dp[n]; } void traverse_add_copy(TreeNode *&root,TreeNode *&dst,int val){ if(root==NULL){ return; } dst=new TreeNode(root->val+val); if(root->left){ traverse_add_copy(root->left,dst->left,val); } if(root->right){ traverse_add_copy(root->right,dst->right,val); } } }; class Solution2 { public: vector<TreeNode*> generateTrees(int n) { vector<TreeNode *>result; helper(1,n,result); return result; } void helper(int start,int end,vector<TreeNode *> &result){ if(start>end){ result.push_back(NULL); return;//左子树必须小于根节点,所以压入NULL } for(int i=start;i<=end;i++){ vector<TreeNode *> tmpLeft,tmpRight; helper(start,i-1,tmpLeft); helper(i+1,end,tmpRight); //生成左右子树,从节点start到i-1,还有就是i+1到end for(int k=0;k<tmpLeft.size();k++){ for(int j=0;j<tmpRight.size();j++){ TreeNode *root=new TreeNode(i); //本质上是中序遍历 root->left=tmpLeft[k]; root->right=tmpRight[j];//左边选择比自己小的,右边选择比自己大的 result.push_back(root); } } } } };