题目见力扣270场周赛第三题从二叉树一个节点到另一个节点每一步的方向
很明显这个题需要我们求解两个节点的最近公共祖先,这样才是最短路径,在求得他们的最近公共祖先后,从这个结点T到出发结点startValue的路径记录在ans1中,从T到目的结点destValue的路径记录在ans2中,我们可以很明显的发现最后的答案就是将ans1中的‘L’和‘R’全部转换成‘U’,然后拼接在ans2之前,就是整个的最短路径。
在求解最近公共祖先时,我们可以采用以下方法:从头节点出发,到起始结点s的路径记录在ans1中,从头节点出发,到目的结点的路径记录在ans2中,那么最近的公共祖先就是两个记录中出现的第一个不同的数字的前一个结点,即最后一个出现的相同的字符。例如:
假设ans1中记录了”LLRL“,ans2中记录了”LRR“,那么,两个结点的最近公共祖先就是头结点的‘L’结点,即头节点的左孩子结点。
同时,因为我们已经遍历从头节点遍历过一次了,必然经过了最近公共祖先,因此不需要从最近公共祖先处再次遍历,只需要删除前面相同的字符然后按照规则拼接即可,例如
对于前一个例子,我们删除相同的字符L,此时ans1中记录了”LRL“,ans2中记录了”RR“,将ans1中的字符换成‘U’,得到ans1中记录为:“UUU”,把ans2拼接在ans1之后,得到最终的ans为:“UUURR”。
代码如下,有部分修改:
bool find(TreeNode* root,int x,vector<char>&ans){
if(root->val==x) return true;
if(root->left){
ans.push_back('L');
if(find(root->left,x,ans)) return true; //如果找到的话就直接返回,就不pop了
ans.pop_back();
}
if(root->right){
ans.push_back('R');
if(find(root->right,x,ans)) return true;
ans.pop_back();
}
return false;
}
string getDirections(TreeNode* root, int startValue, int destValue) {
vector<char>ans1;
vector<char>ans2;
string s="";
find(root,startValue,ans1);
find(root,destValue,ans2);
int n=ans1.size();
int m=ans2.size();
int pos=0;
while(n&&m&&pos<n&&pos<m){
if(ans1[pos]==ans2[pos]){
ans1[pos]=' ';
ans2[pos]=' ';
}
else break;
pos++;
}
for(int i=0;i<n;i++){
if(ans1[i]=='L'||ans1[i]=='R') s+="U";
}
for(int i=0;i<m;i++){
if(ans2[i]!=' ') {
s+=string(1,ans2[i]);
}
}
return s;
}
事实上也可以用图论的方法做,同时,寻找最近公共祖先也有多种方法P236二叉树的最近公共祖先,见博客二叉树的最近公共祖先