第二十七题
两个方法
第一个是通过公共祖先之前的访问路径相同来找
第二个是构造完满二叉树 再用二叉树孩子p的父亲结点是p/2来暴力运算
方法1 找公共路径 匹配公共路径
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
class Solution {
public:
/**
*
* @param root TreeNode类
* @param o1 int整型
* @param o2 int整型
* @return int整型
*/
int findout=0;
int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
// 递归找到 从root到指定点的直接路径
// 因为如果有公共结点 那么这个公共结点到root的路径应该是一样的
// 所以,找到路径之后,再比对两者的公共路径 直到找到第一个不相同
// write code here
vector<int>o_1,o_2;
findout=0;
// 递归返回o_1 就是从root到o1经过的所有的点
findpoint(o_1,root, o1);
// 最后添加一个-1 表示结束了,处理边界问题
// 用来解决 在最后一个o_1 o_2 较短的最后一个匹配了 的边界问题
o_1.push_back(-1);
// 递归调用获得o_2的路径
findout=0;
findpoint(o_2,root, o2);
o_2.push_back(-1);
// 输出o_1、o_2的代码
// for(int i =0;i<o_1.size();i++)
// {
// cout<<o_1[i]<<" ";
// }
// cout<<endl;
// for(int i =0;i<o_2.size();i++)
// {
// cout<<o_2[i]<<" ";
// }
// 因为如果有公共结点 那么这个公共结点到root的路径应该是一样的
// 所以只要一个个往后比较 出现第一个不一样的时候,返回不一样的值的前一个。
for(int i =0;i< min(o_1.size(), o_2.size());i++)
{
if(o_1[i] != o_2[i] )
return o_1[i-1];
}
return -1;
}
// 找到到指定数字的路径
void findpoint(vector<int> &ret_ans,TreeNode* root,int num)
{
if(root==NULL)
return ;
ret_ans.push_back(root->val);
if(root->val == num)
{
findout=1;
return;
}
// 递归找路径
// 如果说已经找到了 直接返回
findpoint(ret_ans,root->left,num);
if(findout==1)
return;
findpoint(ret_ans,root->right,num);
if(findout==1)
return;
// 如果说不是该路径上的点 直接pop扔掉
ret_ans.pop_back();
return;
}
};
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
class Solution {
public:
/**
*
* @param root TreeNode类
* @param o1 int整型
* @param o2 int整型
* @return int整型
*/
int findout=0;
int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
// 递归找到 从root到指定点的直接路径
// 因为如果有公共结点 那么这个公共结点到root的路径应该是一样的
// 所以,找到路径之后,再比对两者的公共路径 直到找到第一个不相同
// write code here
vector<int>o_1,o_2;
findout=0;
// 递归返回o_1 就是从root到o1经过的所有的点
findpoint(o_1,root, o1);
// 最后添加一个-1 表示结束了,处理边界问题
// 用来解决 在最后一个o_1 o_2 较短的最后一个匹配了 的边界问题
o_1.push_back(-1);
// 递归调用获得o_2的路径
findout=0;
findpoint(o_2,root, o2);
o_2.push_back(-1);
// 输出o_1、o_2的代码
// for(int i =0;i<o_1.size();i++)
// {
// cout<<o_1[i]<<" ";
// }
// cout<<endl;
// for(int i =0;i<o_2.size();i++)
// {
// cout<<o_2[i]<<" ";
// }
// 因为如果有公共结点 那么这个公共结点到root的路径应该是一样的
// 所以只要一个个往后比较 出现第一个不一样的时候,返回不一样的值的前一个。
for(int i =0;i< min(o_1.size(), o_2.size());i++)
{
if(o_1[i] != o_2[i] )
return o_1[i-1];
}
return -1;
}
// 找到到指定数字的路径
void findpoint(vector<int> &ret_ans,TreeNode* root,int num)
{
if(root==NULL)
return ;
ret_ans.push_back(root->val);
if(root->val == num)
{
findout=1;
return;
}
// 递归找路径
// 如果说已经找到了 直接返回
findpoint(ret_ans,root->left,num);
if(findout==1)
return;
findpoint(ret_ans,root->right,num);
if(findout==1)
return;
// 如果说不是该路径上的点 直接pop扔掉
ret_ans.pop_back();
return;
}
};
方法2 与25题类似 暴力 构造成满二叉树 在按照满二叉树的性质 向上找结果
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param p int整型
* @param q int整型
* @return int整型
*/
TreeNode* notnode=new TreeNode(-1);
int lowestCommonAncestor(TreeNode* root, int p, int q) {
// write code here
// 知道深度 2^深度-1就是满二叉树的结点个数
int depth = getdepth(root);
// 保存层序遍历的结果
int *cengxv=new int[int(pow(2,depth))];
// 用于层次遍历 保存后续结点的队列
queue<TreeNode *> que;
// 第一次先把根节点放进去
que.push(root);
// 记录当前在第几层从1开始计算
int level=1;
// 层次遍历 如果队列不是空,则继续往下遍历
// 从第一层开始 处理完深度的树
while( level<=depth ){
// length表示这一层存有几个 决定了之后要遍历的次数
int length = que.size();
int k=0;
// 和之字形套路一样 只用队列中的length个
while(length--)
{
// 如果说 这个点是我自己预留出来的空节点 也就是val=-1
if(que.front()->val==-1){
que.pop();
// -1 表示为空 在找父节点的时候使用
cengxv[int(pow(2,level-1))+k] = '-1';
k++;
// 每一个空节点 会产生连个子空节点
que.push(notnode);
que.push(notnode);
continue;
}
// 访问当前结点
TreeNode* thisnode = que.front();
que.pop();
// 把该节点的数据存到序列中
// 每个点的位置是:2^(当前level) +k
cengxv[int(pow(2,level-1))+k]=thisnode->val;
k++;
// 如果左右孩子还有 就push进队列(记住,此时所有入得队列 都代表是下一层的)
// 反之,如果左右孩子是空 就push notnode (用来保证所传递的序列 位置上是有东西的)
if(thisnode->left!=NULL)
que.push(thisnode->left);
else
que.push(notnode);
if(thisnode->right!=NULL)
que.push(thisnode->right);
else
que.push(notnode);
}
// 到下一层处理
level++;
}
int pp=-1,qq=-1;
// 可以取消注释 看一眼所有保存到序列的值
for (int i =1;i<int(pow(2,depth));i++){
if(cengxv[i]==p)
pp=i;
if(cengxv[i]==q)
qq=i;
// cout<<cengxv[i]<<" ";
}
// p q 两个点的位置
cout<< pp<<" "<<qq<<endl;
while(pp!=qq)
{
if(pp > qq)
pp=pp/2;
else
qq=qq/2;
}
return cengxv[pp];
}
// 知道深度 递归调用 就不说了
int getdepth(TreeNode *root){
int depth=0;
if(root==NULL)
return depth;
int leftdepth=getdepth(root->left);
int rightdepth = getdepth(root->right);
depth = leftdepth > rightdepth ? leftdepth:rightdepth;
return depth+1;
}
};
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param p int整型
* @param q int整型
* @return int整型
*/
TreeNode* notnode=new TreeNode(-1);
int lowestCommonAncestor(TreeNode* root, int p, int q) {
// write code here
// 知道深度 2^深度-1就是满二叉树的结点个数
int depth = getdepth(root);
// 保存层序遍历的结果
int *cengxv=new int[int(pow(2,depth))];
// 用于层次遍历 保存后续结点的队列
queue<TreeNode *> que;
// 第一次先把根节点放进去
que.push(root);
// 记录当前在第几层从1开始计算
int level=1;
// 层次遍历 如果队列不是空,则继续往下遍历
// 从第一层开始 处理完深度的树
while( level<=depth ){
// length表示这一层存有几个 决定了之后要遍历的次数
int length = que.size();
int k=0;
// 和之字形套路一样 只用队列中的length个
while(length--)
{
// 如果说 这个点是我自己预留出来的空节点 也就是val=-1
if(que.front()->val==-1){
que.pop();
// -1 表示为空 在找父节点的时候使用
cengxv[int(pow(2,level-1))+k] = '-1';
k++;
// 每一个空节点 会产生连个子空节点
que.push(notnode);
que.push(notnode);
continue;
}
// 访问当前结点
TreeNode* thisnode = que.front();
que.pop();
// 把该节点的数据存到序列中
// 每个点的位置是:2^(当前level) +k
cengxv[int(pow(2,level-1))+k]=thisnode->val;
k++;
// 如果左右孩子还有 就push进队列(记住,此时所有入得队列 都代表是下一层的)
// 反之,如果左右孩子是空 就push notnode (用来保证所传递的序列 位置上是有东西的)
if(thisnode->left!=NULL)
que.push(thisnode->left);
else
que.push(notnode);
if(thisnode->right!=NULL)
que.push(thisnode->right);
else
que.push(notnode);
}
// 到下一层处理
level++;
}
int pp=-1,qq=-1;
// 可以取消注释 看一眼所有保存到序列的值
for (int i =1;i<int(pow(2,depth));i++){
if(cengxv[i]==p)
pp=i;
if(cengxv[i]==q)
qq=i;
// cout<<cengxv[i]<<" ";
}
// p q 两个点的位置
cout<< pp<<" "<<qq<<endl;
while(pp!=qq)
{
if(pp > qq)
pp=pp/2;
else
qq=qq/2;
}
return cengxv[pp];
}
// 知道深度 递归调用 就不说了
int getdepth(TreeNode *root){
int depth=0;
if(root==NULL)
return depth;
int leftdepth=getdepth(root->left);
int rightdepth = getdepth(root->right);
depth = leftdepth > rightdepth ? leftdepth:rightdepth;
return depth+1;
}
};