這道題是求解所有可行的二叉查找樹,從Unique Binary Search Trees中我們已經知道,可行的二叉查找樹的數量是相應的卡特蘭數,不是一個多項式時間的數量級,所以我們要求解所有的樹,自然是不能多項式時間內完成的了。算法上還是用求解NP問題的方法來求解,也就是N-Queens中介紹的在循環中調用遞歸函數求解子問題。思路是每次一次選取一個結點爲根,然後遞歸求解左右子樹的所有結果,最後根據左右子樹的返回的所有子樹,依次選取然後接上(每個左邊的子樹跟所有右邊的子樹匹配,而每個右邊的子樹也要跟所有的左邊子樹匹配,總共有左右子樹數量的乘積種情況),構造好之後作爲當前樹的結果返回。代碼如下:
public ArrayList<TreeNode> generateTrees(int n) {
return helper(1,n);
}
private ArrayList<TreeNode> helper(int left, int right)
{
ArrayList<TreeNode> res = new ArrayList<TreeNode>();
if(left>right)
{
res.add(null);
return res;
}
for(int i=left;i<=right;i++)
{
ArrayList<TreeNode> leftList = helper(left,i-1);
ArrayList<TreeNode> rightList = helper(i+1,right);
for(int j=0;j<leftList.size();j++)
{
for(int k=0;k<rightList.size();k++)
{
TreeNode root = new TreeNode(i);
root.left = leftList.get(j);
root.right = rightList.get(k);
res.add(root);
}
}
}
return res;
}
實現中還是有一些細節的,因爲構造樹時兩邊要遍歷所有左右的匹配,然後接到根上面。當然我們也可以像在Unique Binary Search Trees中那樣存儲所有的子樹歷史信息,然後進行拼合,雖然可以省一些時間,但是最終還是逃不過每個結果要一次運算,時間複雜度還是非多項式的,並且要耗費大量的空間,感覺這樣的意義就不是很大了。