持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
一、题目
给定一颗二叉树,保证每个节点的值不相同,请通过同时给出的两个节点所对应的值v1和v2去查找这两个节点的最近共同祖先节点。
#include<iostream>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
inline TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
int closestAncestor(TreeNode* root, int o1, int o2) {
}
int main(int, char*[])
{
TreeNode root(3);
TreeNode node1(5);
TreeNode node2(1);
TreeNode node3(6);
TreeNode node4(2);
TreeNode node5(7);
TreeNode node6(4);
TreeNode node7(0);
TreeNode node8(8);
root.left = &node1;
root.right = &node2;
node1.left = &node3;
node1.right = &node4;
node4.left = &node5;
node4.right = &node6;
node2.left = &node7;
node2.right = &node8;
cout << "最近的共同祖先是:" << closestAncestor(&root, 2, 7) << endl;
}
二、分析
由题意可知:
每个节点值都不同,可得出每个节点只会跟v1或者v2其中一个相等。
由此特性,我们在遍历的时候可以保证只要找到一个节点后是不会再重复的,所以再回溯的时候就不需要记录找到的这个节点是v1还是v2。
与二叉搜索树一样,也是需要通过比较得出结论,不同的是,这次需要同时比较两个节点。
但是没有比较顺序,所以是用先序、中序、后序其实都是可行的,但是从比较的效率来看,左右的比较需要遍历很多次,而根的比较只有一次,所以同等概率下先序和中序的效率是要高一些的。
三、模拟
- -> 3 没找到
- 3 -> 5 没找到
- 5 -> 6 没找到
- 6 -> 5
- 5 -> 2 找到2,未全部找到,继续
- 2 -> 7 找到7,未全部找到,继续
- 7 -> 2 带着找到一个的结果,与2一起,便找到两个
四、实现
bool dfs(TreeNode* root, int o1, int o2, int* &result){
if(!root || result) return false;
bool s = (root->val == o1 ||root->val == o2);
bool l = dfs(root->left, o1, o2, result);
if(result) return false;
if(s && l){
result = &root->val;
return false;
}else if(s || l){
bool r = dfs(root->right, o1, o2, result);
if(r){
result = &root->val;
}
return true;
}else{
return dfs(root->right, o1, o2, result);
}
}
int closestAncestor(TreeNode* root, int o1, int o2) {
int* result = nullptr;
dfs(root, o1, o2, result);
return *result;
}
五、结言
这道题也是考验了对二叉树遍历的算法,同时也是一道实用题。
创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!