LeetCode基礎_樹_祖先系列
[235] 二叉搜尋樹的最近公共祖先
思路比較簡單,根據二叉搜尋樹性質,要找的node的val只要 p或q->val <= node->val <= q或p->val
class Solution {
public:
TreeNode *recurse(TreeNode *curr, TreeNode *p, TreeNode *q) {
if (curr->val < p->val && curr->val < q->val)
return recurse(curr->right, p, q);
else if (curr->val > p->val && curr->val > q->val)
return recurse(curr->left, p, q);
else
return curr;
}
TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q) {
return recurse(root, p, q);
}
};
[236] 二叉樹的最近公共祖先
簡單思路:On的空間複雜度來記錄根節點到p和q的路徑,遍歷從根到兩者的路徑一直到不同為止。
優化思路:遞迴,空間優化到O1
遇上題類似,只要左樹和右樹都存在p和q,即終止,否則繼續向左樹或右樹走
通過自上而下遞迴,進行優化後,無需重複遍歷。
這道題優化前為 先遞迴判斷條件 後遞迴往下找結果,
而優化後改變成 先遞迴往下找結果 後直接判斷條件並return。
程式碼如下:
class Solution {
public:
TreeNode *recurse(TreeNode *curr, TreeNode *p, TreeNode *q) {
if (!curr)
return nullptr; //可以縮寫,但為保證可讀性
if (curr == p || curr == q) //curr踩中某個點
return curr;
TreeNode *left = recurse(curr->left, p, q);//在此步驟向下遞迴返回的就是符合條件的值 TreeNode *right = recurse(curr->right, p, q); if (left && right) //左右都不為null,說明一邊有p 一邊有q,直接返回 return curr; else if (left) //只有一邊有p和q,另一邊沒有 return left; //這裡經過了優化,因為上面的left已經遞迴過了,已經拿到了正確的結果 //return recurse(curr->left, p, q);//優化前 else if (right) return right; //同上,優化,不做重複遞迴 return nullptr; } TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q) { return recurse(root, p, q); }
};
[572] 另一個樹的子樹
class Solution {
public:
bool isSameTree(TreeNode *s, TreeNode *t) {//遞迴判斷以當前節點為根的樹是否相同
if (!s && !t)
return true;
return s && t && (s->val == t->val) && isSameTree(s->left, t->left) && isSameTree(s->right, t->right) ? true : false;
}
void recurse(TreeNode *s, TreeNode *t, bool &find) {//遞迴判斷每個s點做為根的樹於t樹相同
if (find || !s)
return;
if (s->val == t->val)
find = isSameTree(s, t);
recurse(s->left, t, find);
recurse(s->right, t, find);
}
bool isSubtree(TreeNode *s, TreeNode *t) {//主函式,為了減枝設定find
if (!t)
return true;
bool find = false;
recurse(s, t, find);
return find;
}
};
[508] 出現次數最多的子樹元素和
class Solution {
public:
map<int, int> sum_; //每一個子樹的值,該值出現的次數
int recurse(TreeNode *curr, int &tree_sum) {
if (!curr)
return 0;
int left_sum = recurse(curr->left, tree_sum); //左子樹和
int right_sum = recurse(curr->right, tree_sum); //右子樹和
int now_sum = curr->val + left_sum + right_sum; //以當前節點為根的樹和
sum_[now_sum]++; //當前和出現次數+1
tree_sum += curr->val; //總樹和+當前節點值
return now_sum;
}
vector<int> findFrequentTreeSum(TreeNode *root) {
int tree_sum = 0, max = -1; //樹總和,最大次數
recurse(root, tree_sum);
vector<int> ret;
for (pair p : sum_)
if (p.second == max)
ret.push_back(p.first);
else if (p.second > max) {
max = p.second;
ret.clear();
ret.push_back(p.first);
}
return ret;
}
};