题意:
给一个数n,返回所有能存储1到n的二叉查找树。
分析:
这是个好题,应该考虑深度优先搜索或者动态规划。
递归好理解:
遍历1到n每个数做结点。
对于每一个根节点,将左边的结点能构造出的的所有树 以及 将右边的结点能构造出的所有树 求其笛卡尔积:即双重循环遍历。
那么,怎么得到呢?递归,传的参数应该就是一串数,递归中又遍历这串数.......
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public List<TreeNode> generateTrees(int n) { if(n == 0) return new ArrayList<>(); return trees(1, n); } private List<TreeNode> trees(int start, int end){ List<TreeNode> roots = new ArrayList<>(); if(start > end){ roots.add(null); return roots; } for(int rootval=start; rootval<=end; rootval++){ //遍历n个数,每个都可能做根结点 List<TreeNode> lefttrees = trees(start, rootval-1); List<TreeNode> righttrees = trees(rootval+1, end); //左子树右子树的情况由于不是动态规划,没有存储,所以需要递归生成 for(TreeNode lefttree : lefttrees){ for(TreeNode righttree : righttrees){ TreeNode root = new TreeNode(rootval); root.left = lefttree; root.right = righttree; roots.add(root); } } } return roots; } }算法的思想是一样的,注意要右边的结点加值即可(注意需要重新构造)
1 2 3 4 5 6 7
对于3作为根节点左子树的形状先忽略,但肯定是12来组成
对于3作为根节点右子树的形状先忽略,但肯定是4567来构成
所以我们的dp数组里面存储的应该是List<TreeNode> 因为每N个结点有多种不同的构造形状。
所以:
3的左子树就是 dp[ 2 ]的所有
3的右子树就是dp[ 4 ]的所有,但是注意,dp[ 3 ]里存储的是 1 2 3 4而不是 4 5 6 7,所以不能直接赋值,需要构造。
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public static List<TreeNode> generateTrees(int n) { List<TreeNode>[] dp = new List[n + 1]; dp[0] = new ArrayList<TreeNode>(); if (n == 0) { return dp[0]; } dp[0].add(null); for (int i = 1; i <= n; i++) { dp[i] = new ArrayList<TreeNode>(); //n个数是的所有情况 for (int rootval = 1; rootval <= i; rootval++) { //每个数都可能做根结点 int leftnum = rootval - 1; int rightnum = i - rootval; for (TreeNode left : dp[leftnum]) { for (TreeNode right : dp[rightnum]) { TreeNode root = new TreeNode(rootval); root.left = left; root.right = addVal(right, leftnum + 1); dp[i].add(root); } } } } return dp[n]; } private static TreeNode addVal(TreeNode root, int val) { if (root == null) { return null; } TreeNode node = new TreeNode(root.val + val); //对每个结点的操作应该是重新构造,否则会改变本身存储的内容 node.left = addVal(root.left, val); node.right = addVal(root.right, val); return node; } }