二叉树常见基础问题
1.普通二叉树的LCA如何求(朴素做法)
两种情况
第一种,p和q是分开的。
第二种,其中一个是lca。
从根节点开始遍历,如果碰到了p或q那么这个节点就是lca,如果一个节点左右子树均有p或q,那么这个节点是lca。
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==NULL||root==p||root==q)
{
return root;
}
TreeNode* l=lowestCommonAncestor(root->left,p,q);
TreeNode* r=lowestCommonAncestor(root->right,p,q);
if(l==NULL&&r==NULL)
{
return NULL;
}
if(l!=NULL&&r!=NULL)
{
return root;
}
return l!=NULL?l:r;
}
};
2.求二叉搜索树的lca
二叉搜索树,指的是任何一个节点左子树的数字必然小于这个节点,而右子树的数字必然大于这个节点。
利用这个性质,我们在找lca的时候可以更方便一些,假设两个节点是p,q,且p<q,那么如果遍历到一个点,这个节点<p,那么显然lca一定在右子树上,如果这个节点>q,那么lca一定在左子树上,如果p<该节点<q,那么这个节点就是lca.
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
while (root->val != p->val && root->val != q->val) {
if (min(p->val, q->val) < root->val &&
max(p->val, q->val) > root->val) {
break;
}
if (root->val < min(p->val, q->val)) {
root = root->right;
} else {
root = root->left;
}
}
return root;
}
};
3.给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
类似于dfs,需要回溯,准备一个二维答案数组,然后从根节点开始dfs,碰到叶子节点就判断是否满足条件,如果满足就将临时路径数组加入答案数组。
class Solution {
public:
void f(TreeNode* root, int aim, int sum, vector<vector<int>>& ans,
vector<int>& p) {
if (root->left == nullptr && root->right == nullptr) {
if (sum + root->val == aim) {
p.push_back(root->val);
ans.push_back(p);
p.pop_back();
}
} else {
p.push_back(root->val);
if (root->left != nullptr) {
f(root->left, aim, sum + root->val, ans, p);
}
if (root->right != nullptr) {
f(root->right, aim, sum + root->val, ans, p);
}
p.pop_back();
}
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<vector<int>> ans;
if (root != nullptr) {
vector<int> p;
f(root, targetSum, 0, ans, p);
}
return ans;
}
};
4.判断一个二叉树是否为平衡二叉树
平衡二叉树,即任何一个节点的左右子树高度差不超过1.
由此性质,我们可以通过递归判断。
class Solution {
public:
bool ok = true;
int f(TreeNode* root) {
if (!ok || root == nullptr) {
return 0;
}
int l = f(root->left);
int r = f(root->right);
if (abs(l - r) > 1) {
ok = false;
}
return max(l, r) + 1;
}
bool isBalanced(TreeNode* root) {
int ans = f(root);
return ok;
}
};
5.判断一个二叉树是不是搜索二叉树
方法:通过中序遍历的方式,遍历数字应该是递增的。
class Solution {
public:
bool isValidBST(TreeNode* root) {
TreeNode* mi = nullptr;
stack<TreeNode*> p;
while ((!p.empty()) || root != nullptr) {
if (root != nullptr) {
p.push(root);
root = root->left;
} else {
root = p.top();
p.pop();
if (mi != nullptr && mi->val >= root->val) {
return false;
}
mi = root;
root = root->right;
}
}
return true;
}
};
6.修剪搜索二叉树
https://leetcode.cn/problems/trim-a-binary-search-tree/
采用递归的方法,先判断当前节点是否满足条件,不满足则向下递归,如果满足条件,那么修改左右孩子的值,返回即可。
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == nullptr) {
return nullptr;
}
if (root->val > high) {
return trimBST(root->left, low, high);
}
if (root->val < low) {
return trimBST(root->right, low, high);
}
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
return root;
}
};
7.二叉树上的打家劫舍问题
https://leetcode.cn/problems/house-robber-iii/description/
感觉有点树形dp的影子,定义两个全局变量yes,no,每次完成一个函数,yes变为选这个点获得的最大值,no变为不选这个点获得的最大值。
class Solution {
public:
int yes = 0, no = 0;
void f(TreeNode* cur) {
if (cur == nullptr) {
yes = 0, no = 0;
return;
}
int y = cur->val;
int n = 0;
f(cur->left);
y += no;
n += max(yes, no);
f(cur->right);
y += no;
n += max(yes, no);
yes = y;
no = n;
}
int rob(TreeNode* root) {
f(root);
return max(yes, no);
}
};

浙公网安备 33010602011771号