leetcode 863. 二叉树中第二小的节点 bfs搜索+dfs建图 模板题

该题链接点击这里

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

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

        

        看到要求我们返回所有离某节点距离为k的节点,我们应该想到使用广度优先搜索,向外迈出k步,然后得到我们需要的节点。这基本上属于一道中规中矩的模板题,技巧点可能在于图的建立。

        一般情况下我们可以通过情况来判断该如何建立图的模型,这里,考虑到从二叉树来构造图,会带来坐标难以表示的问题,我们选用邻接表结构进行建图。

题目中给我们了二叉树节点的定义:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

我们根据定义建立邻接链表即可,为了方便,我们使用map数据结构,结合vector或list来完成图的表示:(这里使用vector)

        unordered_map<TreeNode*, vector<TreeNode*>>mp;

        解释:key为每一个节点,vector中存有与key相邻的每一个节点。

        接着,我们使用树的前序遍历来完成建图过程:

由于每个节点与父节点,左右节点相邻,所以我们做三次判断,若相邻节点不为空,就加入邻接表:

/*

    root为当前节点 father为父节点 
    前序遍历就可建图
    初始化时传入整棵树的根节点 此时father参数为nullptr

*/

void dfs(TreeNode* root,TreeNode* father){
    if(!root)return;
    if(father)mp[root].push_back(father);
    if(root->left)mp[root].push_back(root->left);
    if(root->right)mp[root].push_back(root->right);
    dfs(root->left, root);
    dfs(root->right, root);
}

    

我们使用set判断是否遍历到当前节点:

unordered_set<TreeNode*>s;

定义bfs函数,返回距离target节点步长为k的节点队列:

 queue<TreeNode*>bfs(TreeNode* target,int k){
        queue<TreeNode*>q;
        q.push(target);
        //s为集合 保证只遍历每个元素一次 初始化时讲target加入
        s.insert(target);
        for(int i=0;i<k;i++){
            //向外走k步
            int n=q.size();
            //当前队列中的节点全都向外走一步
            for(int j=0;j<n;j++){
                TreeNode* cur=q.front();
                q.pop();
                for(auto next:mp[cur]){
                    //如果当前节点的邻接节点没有遍历 就遍历
                    if(!s.count(next)){
                        q.push(next);
                        s.insert(next);
                    }
                }
            }
        }
        return q;
    }

这样我们就得到了结果。

完整的代码段如下(leetcode核心代码模式下,无输入输出):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
unordered_map<TreeNode*, vector<TreeNode*>>mp;
unordered_set<TreeNode*>s;
void dfs(TreeNode* root,TreeNode* father){
    if(!root)return;
    if(father)mp[root].push_back(father);
    if(root->left)mp[root].push_back(root->left);
    if(root->right)mp[root].push_back(root->right);
    dfs(root->left, root);
    dfs(root->right, root);
}
    vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {
        dfs(root, nullptr);
        queue<TreeNode*>q=bfs(target,k);
        vector<int>ans;
        while(!q.empty()){
            ans.push_back(q.front()->val);
            q.pop();
        }
        return ans;
    }
    queue<TreeNode*>bfs(TreeNode* target,int k){
        queue<TreeNode*>q;
        q.push(target);
        s.insert(target);
        for(int i=0;i<k;i++){
            int n=q.size();
            for(int j=0;j<n;j++){
                TreeNode* cur=q.front();
                q.pop();
                for(auto next:mp[cur]){
                    if(!s.count(next)){
                        q.push(next);
                        s.insert(next);
                    }
                }
            }
        }
        return q;
    }
};

希望这篇文章对你有帮助。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值