【树的DFS】【LCA】个人练习-Leetcode-2096. Step-By-Step Directions From a Binary Tree Node to Another

题目链接: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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值