leetcode 95. Unique Binary Search Trees II(dp)

题意:

给你n个结点,求所有不同形态的二叉搜索树(BST)。

思路:

枚举每个结点作为根节点时的BST,对于每个根节点,枚举所有不同形态的左子树和右子树,根据BST的定义,左子树和右子树必须也是BST,那么求不同形态子树时又可以用同样的方法,这就成了求解子问题(dp)题目。

由于这题给的数据是1~n的整数,所以当i为根节点时,左子树的值有小于i(即1~i-1),同理右子树为(i+1~n);

java代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<TreeNode> generateTrees(int n) {
        if(n<1){
            return new ArrayList();
        }
        return dfs(1,n);
    }
    public List<TreeNode> dfs(int s,int e){
        if(s>e){
            List<TreeNode> temp = new ArrayList();
            temp.add(null);
            return temp;
        }
        List<TreeNode> ans = new ArrayList();
        for(int i = s;i<=e;i++){
            List<TreeNode> lList = dfs(s,i-1);
            List<TreeNode> rList = dfs(i+1,e);
            for(TreeNode left:lList){
                for(TreeNode right:rList){
                    TreeNode root = new TreeNode(i);
                    root.left = left;
                    root.right = right;
                    ans.add(root);
                }
            }
        }
        return ans;
    }
}


如果用dfs来求解子问题,子问题并不能保存起来,某个子问题在递归过程会重复进行求解,这大大浪费时间(例如,求1~5的BST时1~4这个子问题求了以此,在求1~6的BST,1~4这个子问题又求了一次,同时1~5又重复求了一遍),所以可以开空间来节省时间,开一个二维数组(元素为链表)dp来保存每个子问题所有的BST形态。

//注意用":"方法访问时,只能访问List接口,不能直接访问ArrayList抽象类。

java代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<TreeNode> generateTrees(int n) {
        if(n<1){
            return new ArrayList();
        }
        List[][] dp = new List[n+2][n+2];
        for(int i = 0;i<n+2;i++){
            for(int j = 0;j<n+2;j++){
                if(i==0){
                    dp[i][j] = new ArrayList();
                    dp[i][j].add(null);
                }
                else{
                    dp[i][j] = new ArrayList();
                }
            }
        }
        for(int i = 1;i<=n;i++){
            for(int j = 1;j<=n-i+1;j++){
                for(int k = j;k<j+i;k++){
                    List<TreeNode> lList = dp[k-j][j];
                    List<TreeNode> rList = dp[j+i-1-k][k+1];
                    for(TreeNode left : lList){
                        for(TreeNode right : rList){
                            TreeNode temp = new TreeNode(k);
                            temp.left = left;
                            temp.right = right;
                            dp[i][j].add(temp);
                        }
                    }
                }
            }
        }
        return dp[n][1];
    }
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值