[LeetCode P96] Unique Binary Search Trees II

原题:

原题:
Given an integer 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

解题思路:
这个题的P97简单版可以用DP解决,可以选择先把P97做了,然后做这题,还是纠结了挺久,主要是在不知道有没有更快的方法的情况下,不敢轻易开码,最后还是选择和P97一样的思路,这里我还是用了DP,用来减少一些花销。
代码如下(思路主要见注释):

// 是一道好题,但这题一直不太敢写,因为我一直觉得会有很简单的方法
// 但是事实证明好像大家都没有想到好的解法
// 那样的话就用上一题的思路解决它吧,我们还是用到了DP
// 不过DP只有在左侧可以复用节点,但是在右侧我们不可以复用结点
// 右侧我们要进行深拷贝,深拷贝可以用递归进行
// ==》DP的时间复杂度和空间复杂度都是比直接递归做要节约挺多的
// 最终的时间复杂度有点太高了,比较难计算
class Solution {
public:
    TreeNode* copyTree(TreeNode* root, int inc){
        // 递归地深拷贝这棵树,注意要加上偏移量
        if (root == NULL) return NULL;
        TreeNode* newRoot = new TreeNode(root->val + inc);
        newRoot->left = copyTree(root->left, inc);
        newRoot->right = copyTree(root->right, inc);
        return newRoot;
    }

    vector generateTrees(int n) {
        const int size = n;
        vector<vector> dp(size+1);
        if(n == 0)return dp[0];
        dp[0].push_back(NULL);
        for (int i = 1; i <= n; ++i)
        {
            // 自底向上构建dp
            for (int j = 1; j <= i; ++j)
            {
                // 选择一个作为根节点
                int leftSize = j - 1;
                int rightSize = i - j;
                for (int k = 0; k < dp[leftSize].size(); ++k)
                {
                    // 左侧的dp[leftSize].size()种可能
                    for (int l = 0; l < dp[rightSize].size(); ++l)
                    {
                        // 右侧的dp[rightSize].size()种可能,注意这棵树里的节点全都要加上j
                        TreeNode *root = new TreeNode(j);
                        root->left = dp[leftSize][k];
                        // 左侧树可以不用更改
                        root->right = copyTree(dp[rightSize][l], j);
                        // 我们可以直接拷贝,由于rightSize+j=i
                        // 所以每次i,这颗右边的树都是不同的,每次都要深拷贝
                        dp[i].push_back(root);
                        // 最后把候选解放进去
                    }
                }
            }
        }
        return dp[n];
    }
};

你可能感兴趣的:(LeetCode,leetcode)