七叶笔记 » golang编程 » LeetCode 力扣官方题解 |863. 二叉树中所有距离为 K 的结点

LeetCode 力扣官方题解 |863. 二叉树中所有距离为 K 的结点

力扣 863. 二叉树中所有距离为 K 的结点

题目描述

给定一个二叉树(具有根结点 root ), 一个目标结点 target ,和一个整数值 K 。

返回到目标结点 target 距离为 K 的所有结点的值的列表。 答案可以以任何顺序返回。

示例 1:

 输入:root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, K = 2
输出:[7,4,1]
解释:
所求结点为与目标结点(值为 5)距离为 2 的结点,
值分别为 7,4,以及 1
注意,输入的 "root" 和 "target" 实际上是树上的结点。
上面的输入仅仅是对这些对象进行了序列化描述。  

提示:

  1. 给定的树是非空的。
  2. 树上的每个结点都具有唯一的值 0 <= node.val <= 500 。
  3. 目标结点 target 是树上的结点。
  4. 0 <= K <= 1000.

方法一:深度优先搜索 + 哈希表

若将 target 当作树的根结点,我们就能从 target 出发,使用深度优先搜索去寻找与 target 距离为 k 的所有结点,即深度为 k 的所有结点。

由于输入的二叉树没有记录父结点,为此,我们从根结点 root 出发,使用深度优先搜索遍历整棵树,同时用一个哈希表记录每个结点的父结点。

然后从target 出发,使用深度优先搜索遍历整棵树,除了搜索左右儿子外,还可以顺着父结点向上搜索。

代码实现时,由于每个结点值都是唯一的,哈希表的键可以用结点值代替。此外,为避免在深度优先搜索时重复访问结点,递归时额外传入来源结点 from,在递归前比较目标结点是否与来源结点相同,不同的情况下才进行递归。

C++

 class Solution {
    unordered_map<int, TreeNode*> parents;
    vector<int> ans;

    void findParents(TreeNode* node) {
        if (node->left != nullptr) {
            parents[node->left->val] = node;
            findParents(node->left);
        }
        if (node->right != nullptr) {
            parents[node->right->val] = node;
            findParents(node->right);
        }
    }

    void findAns(TreeNode* node, TreeNode* from, int depth, int k) {
        if (node == nullptr) {
            return;
        }
        if (depth == k) {
            ans.push_back(node->val);
            return;
        }
        if (node->left != from) {
            findAns(node->left, node, depth + 1, k);
        }
        if (node->right != from) {
            findAns(node->right, node, depth + 1, k);
        }
        if (parents[node->val] != from) {
            findAns(parents[node->val], node, depth + 1, k);
        }
    }

public:
    vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {
        // 从 root 出发  DFS ,记录每个结点的父结点
        findParents(root);

        // 从 target 出发 DFS,寻找所有深度为 k 的结点
        findAns(target, nullptr, 0, k);

        return ans;
    }
};
  

Java

 class Solution {
    Map<Integer, TreeNode> parents = new  HASH Map<Integer, TreeNode>();
    List<Integer> ans = new ArrayList<Integer>();

    public List<Integer> distanceK(TreeNode root, TreeNode target, int k) {
        // 从 root 出发 DFS,记录每个结点的父结点
        findParents(root);

        // 从 target 出发 DFS,寻找所有深度为 k 的结点
        findAns(target, null, 0, k);

        return ans;
    }

    public void findParents(TreeNode node) {
        if (node.left != null) {
            parents.put(node.left.val, node);
            findParents(node.left);
        }
        if (node.right != null) {
            parents.put(node.right.val, node);
            findParents(node.right);
        }
    }

    public void findAns(TreeNode node, TreeNode from, int depth, int k) {
        if (node == null) {
            return;
        }
        if (depth == k) {
            ans.add(node.val);
            return;
        }
        if (node.left != from) {
            findAns(node.left, node, depth + 1, k);
        }
        if (node.right != from) {
            findAns(node.right, node, depth + 1, k);
        }
        if (parents.get(node.val) != from) {
            findAns(parents.get(node.val), node, depth + 1, k);
        }
    }
}  

C#

 public class Solution {
    Dictionary<int, TreeNode> parents = new Dictionary<int, TreeNode>();
    IList<int> ans = new List<int>();

    public IList<int> DistanceK(TreeNode root, TreeNode target, int k) {
        // 从 root 出发 DFS,记录每个结点的父结点
        FindParents(root);

        // 从 target 出发 DFS,寻找所有深度为 k 的结点
        FindAns(target, null, 0, k);

        return ans;
    }

    public void FindParents(TreeNode node) {
        if (node.left != null) {
            parents.Add(node.left.val, node);
            FindParents(node.left);
        }
        if (node.right != null) {
            parents.Add(node.right.val, node);
            FindParents(node.right);
        }
    }

    public void FindAns(TreeNode node, TreeNode from, int depth, int k) {
        if (node == null) {
            return;
        }
        if (depth == k) {
            ans.Add(node.val);
            return;
        }
        if (node.left != from) {
            FindAns(node.left, node, depth + 1, k);
        }
        if (node.right != from) {
            FindAns(node.right, node, depth + 1, k);
        }
        TreeNode parent = parents.ContainsKey(node.val) ? parents[node.val] : null;
        if (parent != from) {
            FindAns(parent, node, depth + 1, k);
        }
    }
}
  

Golang

 func distanceK(root, target *TreeNode, k int) (ans []int) {
    // 从 root 出发 DFS,记录每个结点的父结点
    parents := map[int]*TreeNode{}
    var findParents func(*TreeNode)
    findParents = func(node *TreeNode) {
        if node.Left != nil {
            parents[node.Left.Val] = node
            findParents(node.Left)
        }
        if node.Right != nil {
            parents[node.Right.Val] = node
            findParents(node.Right)
        }
    }
    findParents(root)

    // 从 target 出发 DFS,寻找所有深度为 k 的结点
    var findAns func(*TreeNode, *TreeNode, int)
    findAns = func(node, from *TreeNode, depth int) {
        if node == nil {
            return
        }
        if depth == k { // 将所有深度为 k 的结点的值计入结果
            ans = append(ans, node.Val)
            return
        }
        if node.Left != from {
            findAns(node.Left, node, depth+1)
        }
        if node.Right != from {
            findAns(node.Right, node, depth+1)
        }
        if parents[node.Val] != from {
            findAns(parents[node.Val], node, depth+1)
        }
    }
    findAns(target, nil, 0)
    return
}  

C

 struct  HashTable  {
    int key;
    struct TreeNode* val;
    UT_hash_handle hh;
};

void modify(struct HashTable** hashTable, int ikey, struct HashTable* ival) {
    struct HashTable* iter;
    HASH_FIND_INT(*hashTable, &ikey, iter);
    if (iter == NULL) {
        iter = malloc(sizeof(struct HashTable));
        iter->key = ikey;
        iter->val = ival;
        HASH_ADD_INT(*hashTable, key, iter);
    } else {
        iter->val = ival;
    }
}

 struct  HashTable* query(struct HashTable** hashTable, int ikey) {
    struct HashTable* iter;
    HASH_FIND_INT(*hashTable, &ikey, iter);
    if (iter == NULL) {
        return NULL;
    }
    return iter->val;
}

struct HashTable* parents;
int* ans;
int ansSize;

 void  findParents(struct TreeNode* node) {
    if (node->left != NULL) {
        modify(&parents, node->left->val, node);
        findParents(node->left);
    }
    if (node->right != NULL) {
        modify(&parents, node->right->val, node);
        findParents(node->right);
    }
}

void findAns(struct TreeNode* node, struct TreeNode* from, int depth, int k) {
    if (node == NULL) {
        return;
    }
    if (depth == k) {
        ans[ansSize++] = node->val;
        return;
    }
    if (node->left != from) {
        findAns(node->left, node, depth + 1, k);
    }
    if (node->right != from) {
        findAns(node->right, node, depth + 1, k);
    }
    if (query(&parents, node->val) != from) {
        findAns(query(&parents, node->val), node, depth + 1, k);
    }
}

int* distanceK(struct TreeNode* root, struct TreeNode* target, int k, int* returnSize) {
    parents = NULL;
    ans =  malloc (sizeof(int) * 500);
    ansSize = 0;

    // 从 root 出发 DFS,记录每个结点的父结点
    findParents(root);

    // 从 target 出发 DFS,寻找所有深度为 k 的结点
    findAns(target, NULL, 0, k);

    *returnSize = ansSize;
    return ans;
}  

JavaScript

 var distanceK = function(root, target, k) {
    const parents = new Map();
    const ans = [];

    const findParents = (node) => {
        if (node.left != null) {
            parents.set(node.left.val, node);
            findParents(node.left);
        }
        if (node.right != null) {
            parents.set(node.right.val, node);
            findParents(node.right);
        }
    }

    // 从 root 出发 DFS,记录每个结点的父结点
    findParents(root);

    const findAns = (node, from, depth, k) => {
        if (node == null) {
            return;
        }
        if (depth === k) {
            ans.push(node.val);
            return;
        }
        if (node.left !== from) {
            findAns(node.left, node, depth + 1, k);
        }
        if (node.right !== from) {
            findAns(node.right, node, depth + 1, k);
        }
        if (parents.get(node.val) !== from) {
            findAns(parents.get(node.val), node, depth + 1, k);
        }
    }
    // 从 target 出发 DFS,寻找所有深度为 k 的结点
    findAns(target, null, 0, k);

    return ans;
};
  

复杂度分析

  • 时间复杂度:O(n),其中n是二叉树的结点个数。需要执行两次深度优先搜索,每次的时间复杂度均为O(n)。
  • 空间复杂度:O(n) 。记录父节点需要O(n)的空间,深度优先搜索需要O(n)的栈空间。

本文作者:力扣

声明:本文归“力扣”版权所有,如需转载请联系。

相关文章