Leetcode:96.不同的二叉搜尋樹&&Leetcode:95.不同的二叉搜尋樹II
Leetcode:96.不同的二叉搜尋樹
給定一個整數 n,求以 1 ... n 為節點組成的二叉搜尋樹有多少種?
示例:
輸入: 3 輸出: 5 解釋: 給定 n = 3, 一共有 5 種不同結構的二叉搜尋樹: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
解題思路:
核心思想:卡特蘭數列,動態規劃(DP)。
f(n)=f(0)*f(n-1)+f(1)*f(n-2)+f(2)*f(n-3)+......+f(n-1)*f(0);
很顯然,如果不用陣列儲存已經算過的值,就要重複計算多次相同的結果,當n非常大時,重複的量也非常多,難免超時。
class Solution { public: int numTrees(int n) { if (n == 0) return 1; if (n == 1) return 1; if (data[n] != 0) return data[n]; int sum = 0; for (int i = 1; i <= n; i++) { sum += numTrees(i - 1)*numTrees(n - i); } data[n] = sum; return sum; } private: vector<int> data = vector<int>(10000, 0); }; |
Leetcode:95.不同的二叉搜尋樹II
核心思想:卡特蘭數列,遞迴,動態規劃。先按照遞迴的思想生成n個結點所有形狀的樹,之後再將1-n按照中序遍歷的順序寫入樹中。
根據這題,本人編寫了如下的關於二叉樹的幾個功能。
1. 樹的複製。複製一個二叉樹,形狀與root相同,但是重新分配了記憶體。
TreeNode* copyTree(TreeNode* root);
2. 查詢n個結點的樹的形狀。將他們的根結點儲存起來,確保這些樹沒有共同的結點。
vector<TreeNode*> find(int n);
3. 按照中序遍歷的順序,將1-n寫入一個二叉樹中。
void In_order(TreeNode* root);
這個程式碼最快速度為16ms,多次出現,相比8ms,12ms的程式碼而言,我覺得主要的差距在於,我這個生成樹的形狀之後,將所有結點賦值為0,最後又要按照中序遍歷順序將1-n賦值到結點中,這裡出現了多餘的2倍操作,但是按照這個思路不太好一開始將應有的數值賦值,後續仍需改進。
#define hasLChild(x) (!(x->left==NULL)) #define hasRChild(x) (!(x->right==NULL)) class Solution { public: vector<TreeNode*> generateTrees(int n) { if (n <= 0) return{}; vector<TreeNode*> res = find(n); //將中序遍歷所有二叉樹,將1-n寫入樹中 for (int i = 1; i <= int(res.size()); i++) { num = 1; In_order(res[i - 1]); } return res; } void In_order(TreeNode* root) { if (hasLChild(root)) In_order(root->left); root->val = num; num++; if (hasRChild(root)) In_order(root->right); } vector<TreeNode*> find(int n) { if (n == 0) return{ NULL }; if (n == 1) return{ new TreeNode(0) }; if (int(dp[n].size()) > 0) return dp[n]; vector<TreeNode*> res; vector<TreeNode*> data1, data2; for (int i = 1; i <= n; i++) { data1 = find(i - 1); data2 = find(n - i); for (int j = 1; j <= int(data1.size()); j++) { for (int k = 1; k <= int(data2.size()); k++) { TreeNode* temp = new TreeNode(0); temp->right = copyTree(data1[j - 1]); temp->left = copyTree(data2[k - 1]); res.push_back(temp); } } } dp[n] = res; return res; } TreeNode* copyTree(TreeNode* root) {//將root複製到copy中 TreeNode* copy; if (root == NULL) { copy = NULL; return copy; } copy = new TreeNode(0); queue<TreeNode*> Qr, Qc; TreeNode* tempr,*tempc; Qr.push(root); Qc.push(copy); while (!Qr.empty()) { tempr = Qr.front(); tempc = Qc.front(); Qr.pop(); Qc.pop(); if (hasLChild(tempr)) { tempc->left = new TreeNode(0); Qr.push(tempr->left); Qc.push(tempc->left); } if (hasRChild(tempr)) { tempc->right = new TreeNode(0); Qr.push(tempr->right); Qc.push(tempc->right); } } return copy; } private: int num = 0; vector<TreeNode*> dp[1000]; }; |
參考的別人的更優秀的程式碼,學到了很多,平均用時12ms,如下。
class Solution { if(b>e){ |