📌  相关文章
📜  二叉树中节点的第 K 个祖先 |设置 2(1)

📅  最后修改于: 2023-12-03 15:36:03.377000             🧑  作者: Mango

二叉树中节点的第 K 个祖先

在二叉树中,每个节点都具有唯一的父节点(除了根节点)。因此,可以通过向上遍历树来找到节点的祖先节点。本文将介绍如何在二叉树中找到节点的第 K 个祖先节点。

方法一:递归

首先,我们可以使用递归的方法,从当前节点开始向上遍历树。具体地说,如果当前节点是目标节点,我们直接返回该节点自身;否则,我们递归遍历该节点的左右子树。如果左右子树中均未找到目标节点,我们返回空指针;否则,我们返回目标节点或找到的祖先节点之一。

TreeNode* findKthAncestor(TreeNode* root, TreeNode* target, int k) {
    if (root == nullptr) return nullptr;
    if (root == target || (left && right)) return root;
    auto left = findKthAncestor(root->left, target, k);
    auto right = findKthAncestor(root->right, target, k);
    if (left) {  // target found in left subtree
        if (k > 1) return findKthAncestor(left, target, k - 1);
        else return root;
    } else if (right) {  // target found in right subtree
        if (k > 1) return findKthAncestor(right, target, k - 1);
        else return root;
    } else {  // target not found
        return nullptr;
    }
}

在上述代码中,我们定义了一个名为 findKthAncestor 的函数,该函数接受三个参数:二叉树根节点 root、目标节点 target 和要找到的祖先层数 k。当 root 为空指针时,我们返回空指针;当 root 等于 target 或者 target 的左右子树中均有一个非空节点时,我们返回 root 自身。否则,我们递归遍历 root 的左右子树,并在左右子树中查找第 k - 1 个祖先节点,如果找到则返回该节点,否则返回空指针。

方法二:迭代

除了递归之外,我们还可以使用迭代的方式来实现。具体来说,我们可以使用一个栈来存储从根节点到目标节点的路径。然后,我们从栈顶开始向下遍历,直到找到第 k 个祖先节点或者遍历完整个路径。

TreeNode* findKthAncestor(TreeNode* root, TreeNode* target, int k) {
    stack<TreeNode*> path;
    TreeNode* cur = root;
    TreeNode* last = nullptr;
    while (cur || !path.empty()) {
        while (cur) {
            path.push(cur);
            if (cur == target) break;
            cur = cur->left;
        }
        if (path.top() == target) break;
        if (path.top()->right && path.top()->right != last) {
            cur = path.top()->right;
        } else {
            last = path.top();
            path.pop();
        }
    }
    while (k > 1 && !path.empty()) {
        path.pop();
        k--;
    }
    return path.empty() ? nullptr : path.top();
}

在上述代码中,我们定义了一个名为 findKthAncestor 的函数,该函数接受三个参数:二叉树根节点 root、目标节点 target 和要找到的祖先层数 k

首先,我们使用一个栈 path 和指针 cur 来存储从 roottarget 的路径。具体来说,我们从 root 开始向下遍历树,并将经过的节点压入栈中,直到找到目标节点 target 或者遍历完整个路径。然后,我们从栈顶开始向下遍历,如果遍历到了左子树且左子树不为空,则继续往下遍历;否则,如果遍历到了右子树且右子树不为空,则转到右子树继续往下遍历;否则,说明已经遍历到了当前节点的最右子树,我们将当前节点弹出栈,并记录上一个弹出的节点 last

接下来,我们从栈顶开始向下遍历,直到找到第 k 个祖先节点或者遍历完整个路径。具体来说,我们不断弹出栈顶元素,并将计数器 k 减 1,直到 k 等于 1 或者栈为空为止。最后,我们返回栈顶元素或者空指针。