2024.2.29
- 题目来源
- 我的题解
- 方法一 深度搜索(暴力) 超时
- 方法二 树形动态规划
题目来源
力扣每日一题;题序:2581
我的题解
方法一 深度搜索(暴力) 超时
- 以每个节点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]对是否存在,连接成字符串ListList<String> guess=new ArrayList<>();//记录以节点i为根,用户猜对的次数,当然由于在过程中进行了截断,所以最大值为kint[] 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月的每日一题了。😄
有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~