Leetcode 863. All Nodes Distance K in Binary Tree (python)

该博客主要讲解了LeetCode第863题的解决方案,使用Python实现。通过将二叉树转化为图并进行BFS搜索,找到与目标节点距离为K的节点。文章提到了两种将树转化为图的方法,并指出在BFS过程中如何优化以避免访问超出目标距离的节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Leetcode 863. All Nodes Distance K in Binary Tree

题目

在这里插入图片描述
在这里插入图片描述

解析:

这道题看到固定距离寻找这种限制条件,第一个想到的就应该是BFS。所以这道题目变成了两个部分:

  • 将树转化为图,每个节点指向parent节点和左右子节点
  • 从target节点出发,BFS寻找特定距离的点
  • 值得注意的是,这边给的target是节点,所以不需要额外去寻找target节点
    这边将树转化为图有两种做法,一种是利用树的性质,将parent直接作为树节点的属性,代码如下:
class Solution(object):
    def distanceK(self, root, target, K):
        """
        :type root: TreeNode
        :type target: TreeNode
        :type K: int
        :rtype: List[int]
        """
        def add_par(node,par):
            if not node:
                return
            node.par = par
            add_par(node.left,node)
            add_par(node.right,node)
        
        add_par(root,None)
        
        ans = []
        q = collections.deque()
        q.append((target,0))
        visited = set()
        visited.add(target.val)
        while q:
            curr,dis = q.popleft()
            if dis == K:
                ans.append(curr.val)
            for nei in (curr.left,curr.right,curr.par):
                if nei and nei.val not in visited:
                    q.append((nei,dis+1))
                    visited.add(nei.val)
        return ans 

而第二种才是更加标准的做法。将树转化为图通常的表达方式,也就是字典

class Solution(object):
    def distanceK(self, root, target, K):
        """
        :type root: TreeNode
        :type target: TreeNode
        :type K: int
        :rtype: List[int]
        """
        def build_graph(node,par):
            if not node:
                return
            if node.left:
                graph[node].append(node.left)
            if node.right:
                graph[node].append(node.right)
            if par:
                graph[node].append(par)
            build_graph(node.left,node)
            build_graph(node.right,node)
        graph = collections.defaultdict(list)
        build_graph(root,None)
        ans = []
        q = collections.deque()
        q.append((target,0))
        visited = set()
        visited.add(target.val)
        while q:
            node,dis = q.popleft()
            if dis == K:
                ans.append(node.val)
            for nei in graph[node]:
                if nei.val not in visited:
                    q.append((nei,dis+1))
                    visited.add(nei.val)
        return ans

二刷解法:

在bfs里面每次pop出相同距离的所有node,这样超过目标距离的节点就无需访问

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def distanceK(self, root: TreeNode, target: TreeNode, k: int) -> List[int]:
        # transform tree into graph
        g = collections.defaultdict(list)
        def dfs(node):
            if node.left:
                g[node.val].append(node.left.val)
                g[node.left.val].append(node.val)
                dfs(node.left)
            if node.right:
                g[node.val].append(node.right.val)
                g[node.right.val].append(node.val)
                dfs(node.right)
        
        dfs(root)
        # print(g)
        # bfs to find the nodes at k distance
        q = collections.deque()
        visited = {}
        q.append(target.val)
        visited[target.val] = True
        dist = 0
        while q:
            if dist == k:
                return list(q)
            # pop out all the nodes at the current distance
            for _ in range(len(q)):
                curr = q.popleft()
                for neigh in g[curr]:
                    if neigh not in visited:
                        q.append(neigh)
                        visited[neigh] = True
            dist += 1
        return []

c++版本

class Solution {
public:
    void helper(TreeNode* node,unordered_map<int,vector<int>>& g){
        if(!node) return;
        if(node->left){
            g[node->val].push_back(node->left->val);
            g[node->left->val].push_back(node->val);
            helper(node->left,g);
        }
        if(node->right){
            g[node->val].push_back(node->right->val);
            g[node->right->val].push_back(node->val);
            helper(node->right,g);
        }
        return;
    }
    vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {
        unordered_map<int,vector<int>> g;
        helper(root,g);
        queue<int> q;
        unordered_set<int> visited;
        q.push(target->val);
        visited.insert(target->val);
        int dis = 0;
        vector<int> ans;
        while(!q.empty()){
            int n = q.size();
            for(int i=0;i<n;i++){
                int curr = q.front();
                // cout << curr << " " << dis << endl;
                q.pop();
                if(dis == k){
                    ans.push_back(curr);
                }
                for(auto& neigh : g[curr]){
                    if(visited.count(neigh)) continue;
                    q.push(neigh);
                    visited.insert(neigh);
                }
            }
            if(dis == k){
                return ans;
            }
            dis++;
        }
        return ans;
    }
};

时间复杂度:O(n)
空间复杂度:O(n)
n为节点个数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值