package com.example.lettcode.dailyexercises;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* @Class GenerateTrees
* @Description 95 不同的二叉搜索树II
* 给定一个整数 n,生成所有由 1 ... n 为节点所组成的 二叉搜索树 。
* 示例:
* 输入:3
* 输出:
* [
* [1,null,3,2],
* [3,2,null,1],
* [3,1,null,null,2],
* [2,1,3],
* [1,null,2,null,3]
* ]
* 解释:
* 以上的输出对应以下 5 种不同结构的二叉搜索树:
* <p>
* 1 3 3 2 1
* / / /
* 3 2 1 1 3 2
* / /
* 2 1 2 3
* <p>
* 提示:
* 0 <= n <= 8
* @Author
* @Date 2020/7/15
**/
public class GenerateTrees {
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public static List<TreeNode> generateTrees(int n) {
if (n < 1) return new ArrayList<>();
// dp[i] 表示n=i时所能取得的二叉搜索树
List<TreeNode>[] dp = new List[n + 1];
for (int i = 0; i <= n; i++) {
dp[i] = new ArrayList<>();
}
dp[1] = new ArrayList<>(Arrays.asList(new TreeNode(1)));
for (int i = 2; i <= n; i++) {
for (int j = 0; j < i; j++) {
dp[i].addAll(getNodeList(dp, j, i - j - 1));
}
}
return dp[n];
}
private static List<TreeNode> getNodeList(List<TreeNode>[] dp, int i, int j) {
List<TreeNode> res = new ArrayList<>();
// 左子树不变,右子树加上root.val
int sizeL = i == 0 ? 1 : dp[i].size(); // 左子树个数
int sizeR = j == 0 ? 1 : dp[j].size(); // 右子树个数
int size = sizeL * sizeR; // 左右子树的可能性
for (int k = 0; k < size; k++) {
TreeNode root = new TreeNode(i + 1);
// k/sizeR 表示每次以此选择左子树,然后依次把右子树都遍历一遍
root.left = i == 0 ? null : dp[i].get(k / sizeR);
// (k%sizeR) 从0...sizeR-1 + roo.val ,是因为右子树的元素都比根节点大,分别大1,2,3...,sizeR-1
root.right = j == 0 ? null : copyTree(dp[j].get(k % sizeR), root.val);
res.add(root);
}
return res;
}
// 递归是为了右子树的每个元素都加上sizeAdd(也就是根节点的值)
private static TreeNode copyTree(TreeNode treeNode, int sizeAdd) {
if (treeNode == null) return null;
TreeNode node = new TreeNode(treeNode.val + sizeAdd);
node.left = copyTree(treeNode.left, sizeAdd);
node.right = copyTree(treeNode.right, sizeAdd);
return node;
}
public static void main(String[] args) {
int n = 5;
List<TreeNode> treeNodeList = generateTrees(n);
System.out.println("GenerateTrees demo01 result:" + treeNodeList.size());
}
}