題目:
給定一個整數 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 種不同結構的二叉搜索樹:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
思路:在網上找的大神的代碼。原文鏈接:https://blog.csdn.net/onedeveloper/article/details/80169460。
參考了文章https://blog.csdn.net/happyaaaaaaaaaaa/article/details/51635367
今天這個題是真的理解不了。。。。遞歸和二叉樹,還有這個兩層的循環不懂。。。先把其他大神的思路放在這裏。看不懂
1. 每一次都在一個範圍內隨機選取一個結點作爲根。
2. 每選取一個結點作爲根,就把樹切分成左右兩個子樹,直至該結點左右子樹爲空。
大致思路如上,可以看出這也是一個可以劃分成子問題求解的題目,所以考點是動態規劃。
但具體對於本題來說,採取的是自底向上的求解過程。
1. 選出根結點後應該先分別求解該根的左右子樹集合,也就是根的左子樹有若干種,它們組成左子樹集合,根的右子樹有若干種,它們組成右子樹集合。
2. 然後將左右子樹相互配對,每一個左子樹都與所有右子樹匹配,每一個右子樹都與所有的左子樹匹配。然後將兩個子樹插在根結點上。
3. 最後,把根結點放入鏈表中。
(原文:https://blog.csdn.net/ChilseaSai/article/details/50083201)
代碼:
這個代碼我有點看不懂。。。。。。也是用了遞歸的思想
class Solution {
public List<TreeNode> generateTrees(int n) {
if (n < 1) return new ArrayList<>();
//利用一個輔助數組保存中間的值,避免重複求取,但是也會導致有些子樹的結點是公共的
List[][] dp = new List[n + 2][n + 2];
return generateTrees(1, n,dp);
}
private List<TreeNode> generateTrees(int start, int end, List[][] dp) {
List<TreeNode> res = new ArrayList<>();
if (end < start) {
res.add(null);
return res;
}
for (int i = start; i <= end; i++) {
List<TreeNode> list1 = dp[start][i - 1];
if (list1 == null) {
//遞歸,並將結果保存下來
list1 = generateTrees(start, i - 1, dp);
dp[start][i - 1] = list1;
} //(start,i-1)爲左子樹,遍歷不同的左子樹組合
for (TreeNode left : list1) {
List<TreeNode> list2 = dp[i + 1][end];//當 i = n 時,就需要求 dp[n+1][end] 的值
if (list2 == null) {
//遞歸,並將結果保存下來
list2 = generateTrees(i + 1, end, dp);
dp[i + 1][end] = list2;
} //(i+1,end)爲右子樹,遍歷不同的右子樹組合
for (TreeNode right : list2) {
TreeNode root = new TreeNode(i);
root.left = left;
root.right = right;
res.add(root);
}
}
}
return res;
}
}
以下的代碼是另外的一種思路:
我能稍微理解下面這個的思路,就是使用遞歸調用,確定一個根節點,然後在遞歸求解出相應的左子樹和右子樹的各種情況,接着將左右子樹一一配對。但是這個題是怎麼和動態規劃有關係的?主要還是用到遞歸的思想
public class Solution {
public List<TreeNode> generateTrees(int n) {
if(n <= 0) return new ArrayList<>();
return greateSubTree(1, n);
}
private List<TreeNode> greateSubTree(int start, int end) {
List<TreeNode> res = new ArrayList<>();
if(end < start) {
res.add(null);
return res;
}
for(int i = start; i <= end; i++) {
for(TreeNode l : greateSubTree(start, i-1)) { //
for(TreeNode r : greateSubTree(i+1, end)) {
TreeNode root = new TreeNode(i);
root.left = l;
root.right = r;
res.add(root);
}
}
}
return res;
}
}