思路
參考自詳細通俗的思路分析,多解法
利用查找二叉樹的性質。左子樹的所有值小於根節點,右子樹的所有值大於根節點。
所以如果求 1…n 的所有可能。
我們只需要把 1 作爲根節點,[ ] 空作爲左子樹,[ 2 … n ] 的所有可能作爲右子樹。
2 作爲根節點,[ 1 ] 作爲左子樹,[ 3…n ] 的所有可能作爲右子樹。
3 作爲根節點,[ 1 2 ] 的所有可能作爲左子樹,[ 4 … n ] 的所有可能作爲右子樹,然後左子樹和右子樹兩兩組合。
4 作爲根節點,[ 1 2 3 ] 的所有可能作爲左子樹,[ 5 … n ] 的所有可能作爲右子樹,然後左子樹和右子樹兩兩組合。
…
n 作爲根節點,[ 1… n ] 的所有可能作爲左子樹,[ ] 作爲右子樹。
至於,[ 2 … n ] 的所有可能以及 [ 4 … n ] 以及其他情況的所有可能,可以利用上邊的方法,把每個數字作爲
根節點,然後把所有可能的左子樹和右子樹組合起來即可。
特判情況
如果是n==0,那就返回 null。
遞歸邊界
-
如果只有一個數字,那麼所有可能就是一種情況,把該數字作爲一棵樹。
-
如果start<end,則說明此時沒有數字,將null加入結果中
class Solution {
public:
vector<TreeNode*> generateTrees(int n) {
vector<TreeNode*> ans;
//此時沒有數字,將null加入結果中
if (n == 0) return ans;
return getAns(1, n);
}
private:
vector<TreeNode*> getAns(int start, int end)
{
vector<TreeNode*> ans;
//此時沒有數字,將null加入結果中
if (start > end) {
ans.push_back(nullptr);
return ans;
}
//只有一個數字,當前數字作爲一顆樹加入到結果中
if (start==end)
{
TreeNode* tree = new TreeNode(start);
ans.push_back(tree);
return ans;
}
//嘗試每個數組作爲根節點
for (int i=start;i<=end;i++)
{
//得到所有可能的左子樹
vector<TreeNode*> leftTrees = getAns(start, i - 1);//左子樹的所有值小於根節點
//得到所有可能的右子樹
vector<TreeNode*> rightTrees = getAns(i + 1, end);//右子樹的所有值大於根節點
//左子樹右子樹兩兩組合
for (TreeNode* leftTree:leftTrees)
{
for (TreeNode* rightTree:rightTrees)
{
TreeNode* root = new TreeNode(i);
root->left = leftTree;
root->right = rightTree;
//加入到最終結果中
ans.push_back(root);
}
}
}
return ans;
}
};