Leetcode 310. Minimum Height Trees DFS加双key备忘录

  • 从各个点dfs,求出最小的高度
  • memo的key和两者有关,一个是dfs的起点,一个是dfs的根结点,如下图

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

DFS

class Solution {
public:
    // 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
    int h[20005]; //邻接表存储树,有n个节点,所以需要n个队列头节点
    int e[20005]; //存储元素
    int ne[20005]; //存储列表的next值
    int idx; //单链表指针
    int n; //题目所给的输入,n个节点
    vector<int> ans ={20005};

    bool st[20005]; //记录节点是否被访问过,访问过则标记为true
    
    unordered_map<int, int> memo;

    // 添加一条边a->b
    void add(int a, int b)
    {
        e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
    }


    int dfs(int u, int root)
    {
        int key = u*1e5+root;
        if(memo.count(key)) return memo[key];
        int res = INT_MIN; //
        st[u] = true; //标记访问过u节点

        //访问u的每个子节点
        for (int i = h[u]; i != -1; i = ne[i]) {
            int j = e[i];
            if (!st[j]) {
                int s = dfs(j, u);  
                res = max(res, s); 
            }
        }
        
        //memo[key] = res==INT_MIN?1:res+1;
        memo[key] = res+1;
        return memo[key]; 
    }
    
    static bool cmp(const vector<int>& v1, const vector<int>& v2){
        return v1[0]<v2[0];
    }
    
    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
        this->n = n;
        // 初始化
        idx = 0;
        memset(h, -1, sizeof(h));
        for(int i=0; i<edges.size(); i++){
            add(edges[i][0],edges[i][1]);
            add(edges[i][1],edges[i][0]);
        }     
        vector<vector<int>> res;
        for(int i=0; i<n; i++){
            memset(st, false, sizeof(st));
            int height = dfs(i, -1);
            //cout<<"node"<<i<<"  "<<height<<endl;
            res.push_back({height,i});
        }
        //对res排序
        sort(res.begin(), res.end(), cmp);
        vector<int> ans;
        ans.push_back(res[0][1]);
        for(int i=1; i<res.size(); i++){
            if(res[i][0]==res[i-1][0]) 
                ans.push_back(res[i][1]);
            else 
                break;
        }
        return ans;
         
    }
    
};

上面的简版

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
        memset(h, -1, sizeof(h));
        int min_v=INT_MAX;
        vector<int> res;
        for(auto e: edges)
            add(e[0], e[1]), add(e[1], e[0]);
        for(int i=0; i<n; i++){
            memset(st, false, sizeof(st));
            int tmp = dfs(i, -1);
            //cout<<tmp<<" ";
            if(tmp==min_v){
                res.push_back(i);
            }else if(tmp<min_v){
                min_v = tmp;
                res.clear();
                res.push_back(i);
            }
        }
        return res;
    }
private:
    static const int N = 20005;
    int h[N];
    int ne[N];
    int e[N];
    int idx=0;
    bool st[N];
    unordered_map<int, int> memo; 
    
    // 添加点和边
    void add(int a, int b){
        e[idx] = b, ne[idx]=h[a], h[a] = idx++;
    }
    
    // 当前点u的树高
    int dfs(int u, int root){
        int key = u*1e5 +root;
        st[u]=true;
        if(memo.count(key)) return memo[key];
        int max_v = INT_MIN;
        for(int i=h[u]; i!=-1; i=ne[i]){
            int j=e[i];
            if(!st[j]){
                int tmp = dfs(j, u);
                max_v = max(max_v,tmp);
            }
        }
        memo[key] = max_v>0?max_v+1:1; //有问题,如果一个叶子结点,不就会返回(INT_MIN+1)? 的确是这样,但是本题只需通过相对值确定点的编号,无需输出高度,故不影响
        return memo[key];
    }
    
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值