2024.2.29力扣每日一题——统计可能的树根数目

题目来源

力扣每日一题;题序:2581

我的题解

方法一 深度搜索(暴力) 超时
  1. 以每个节点node为跟进行深度搜索,并在搜索过程中记录前驱节点,然后判断[前驱节点,当前节点]是否在guesses中出现。若出现,则表示Bob猜测对一次,并记录在count数组中。最后遍历count数组,看有多少满足count[i]>=k。该值就是可能成为树根的 节点数目

时间复杂度:O( n ( n + e ) n(n+e) n(n+e))。n表示树的节点数,e表示树的边数
空间复杂度:O(n)

class Solution {
	//为了快速判断[u,v]对是否存在,连接成字符串List
    List<String> guess=new ArrayList<>();
    //记录以节点i为根,用户猜对的次数,当然由于在过程中进行了截断,所以最大值为k
    int[] count;
    public int rootCount(int[][] edges, int[][] guesses, int k) {
        int n=edges.length+1;
        count=new int[n];
        List<Integer>[] g=createGraph(n,edges);
        for(int[] t:guesses){
            int u = t[0];
            int v = t[1];
            guess.add(u+"-"+v);
        }
        for(int i=0;i<n;i++){
            dfs(i,i,g,-1,k);
        }
        int res=0;
        for(int i=0;i<n;i++){
            if(count[i]>=k)
                res++;
        }
        return res;
    }
    //深度优先搜索
    public void dfs(int root,int cur,List<Integer>[] g,int pre,int k){
    //根节点没有父节点
        if(pre!=-1){
            String t=pre+"-"+cur;
            //Bob猜测正确
            if(guess.contains(t))
                count[root]++;
            //截断,当已经正确的次数达到k,表明以root为根一定满足
            if(count[root]>=k)
                return;
        }
        for(int next:g[cur]){
        	//防止循环遍历
            if(next!=pre){
                dfs(root,next,g,cur,k);
            }
        }
    }
    //构建树
    public List<Integer>[] createGraph(int n,int[][] edges){
        List<Integer>[] g=new ArrayList[n];
        for(int i=0;i<n;i++){
            g[i]=new ArrayList<>();
        }
        for(int[] t:edges){
            int from=t[0];
            int to = t[1];
            g[from].add(to);
            g[to].add(from);
        }
        return g;
    }
}
//优化版本,但是还是超时
// 利用了如下的结论进行优化。
//基于已经计算出以 x 为树根时猜对的次数,很容易就可以计算出以 y 为树根时猜对的次数:
//如果 (x,y) 存在于 guesses,猜对次数减一;
//如果 (y,x) 存在于 guesses,猜对次数加一。

class Solution {
    List<String> guess=new ArrayList<>();
    int cnt=0;
    int res=0;
    public int rootCount(int[][] edges, int[][] guesses, int k) {
        int n=edges.length+1;
        // count=new int[n];
        List<Integer>[] g=createGraph(n,edges);
        
        for(int[] t:guesses){
            int u = t[0];
            int v = t[1];
            guess.add(u+"-"+v);
        }
        dfs(0,0,g,-1,k);
        rdfs(g,0,-1,k,cnt);
        return res;
    }
    public void rdfs(List<Integer>[] g,int x,int t,int k,int cnt){
        if(cnt>=k){
            res++;
        }
        for(int y:g[x]){
            if(t==y)
                continue;
            
            rdfs(g,y,x,k,cnt-(guess.contains(x+"-"+y)?1:0)+(guess.contains(y+"-"+x)?1:0));
        }
    }
    public void dfs(int root,int cur,List<Integer>[] g,int pre,int k){
        if(pre!=-1){
            String t=pre+"-"+cur;
            if(guess.contains(t))
                cnt++;
        }
        for(int next:g[cur]){
            if(next!=pre){
                dfs(root,next,g,cur,k);
            }
        }
    }
    public List<Integer>[] createGraph(int n,int[][] edges){
        List<Integer>[] g=new ArrayList[n];
        for(int i=0;i<n;i++){
            g[i]=new ArrayList<>();
        }
        for(int[] t:edges){
            int from=t[0];
            int to = t[1];
            g[from].add(to);
            g[to].add(from);
        }
        return g;
    }
}

方法二 树形动态规划

官方题解吧,弄不明白

终于补完2月的每日一题了。😄

有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜菜的小彭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值