题目链接:https://leetcode.cn/problems/step-by-step-directions-from-a-binary-tree-node-to-another/
题目大意:给出一棵二叉树,有n
个节点,其元素值互不相同,从1~n
。给出开始节点的值startValue
和结束节点的值destValue
,求在树中,从开始节点到结束节点的最短路径。要求返回一个string
,表示这条路径,用U
表示向上走,用L/R
表示走到左儿子或者右儿子。
思路:找到两个节点的LCA(Lowest Common Ancestor),最短路径就是从start -> LCA -> dest。DFS得到从root到start和root到dest的路径,这两个路径的【最长的相同前缀】的【最后一个元素】就是LCA
DFS(root, startValue, path2s);
DFS(root, destValue, path2t);
string ret = "";
int len = min(path2s.size(), path2t.size());
int pos;
for (pos = 0; pos < len; pos++) {
if (path2s[pos] != path2t[pos])
break;
}
pos--;
随后,在path2s
中,从末尾(也就是start)开始,遍历到pos的儿子,每一次都是向上走,增加一个U
;在path2t
中,从pos
开始,遍历到末尾(也就是dest),如果走左儿子,就加L
,反之加R
。
for (int i = path2s.size()-1; i > pos; i--)
ret += "U";
for (int i = pos; i < path2t.size()-1; i++) {
if (path2t[i+1] == leftSon[path2t[i]])
ret += "L";
else
ret += "R";
}
其中,左儿子的情况在DFS时就记录下来。虽然出于完整性或者强迫症考虑可以加上【右儿子的记录】,但实际上我们需要的只是【判断路径中的下一个元素是上一个元素的左儿子还是右儿子】即可,非左即右,为了节省空间,可以只记录左儿子。
bool DFS(TreeNode* node, int tgt, vector<int>& path) {
if (node == nullptr)
return false;
path.emplace_back(node->val);
if (node->left)
leftSon[node->val] = node->left->val;
if (node->val == tgt)
return true;
if (DFS(node->left, tgt, path) || DFS(node->right, tgt, path))
return true;
path.pop_back();
return false;
}
完整代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> path2s, path2t;
int leftSon[100001];
bool DFS(TreeNode* node, int tgt, vector<int>& path) {
if (node == nullptr)
return false;
path.emplace_back(node->val);
if (node->left)
leftSon[node->val] = node->left->val;
if (node->val == tgt)
return true;
if (DFS(node->left, tgt, path) || DFS(node->right, tgt, path))
return true;
path.pop_back();
return false;
}
string getDirections(TreeNode* root, int startValue, int destValue) {
memset(leftSon, 0, sizeof(leftSon));
path2s.clear();
path2t.clear();
DFS(root, startValue, path2s);
DFS(root, destValue, path2t);
string ret = "";
int len = min(path2s.size(), path2t.size());
int pos;
for (pos = 0; pos < len; pos++) {
if (path2s[pos] != path2t[pos])
break;
}
pos--;
for (int i = path2s.size()-1; i > pos; i--)
ret += "U";
for (int i = pos; i < path2t.size()-1; i++) {
if (path2t[i+1] == leftSon[path2t[i]])
ret += "L";
else
ret += "R";
}
return ret;
}
};