2024.2.29
题目来源
我的题解
方法一 深度搜索(暴力) 超时
- 以每个节点node为跟进行深度搜索,并在搜索过程中记录前驱节点,然后判断[前驱节点,当前节点]是否在guesses中出现。若出现,则表示Bob猜测对一次,并记录在count数组中。最后遍历count数组,看有多少满足count[i]>=k。该值就是可能成为树根的 节点数目
时间复杂度 :O( n ( n + e ) n(n+e) n(n+e))。n表示树的节点数,e表示树的边数
空间复杂度:O(n)
java
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;
}
}
java
//优化版本,但是还是超时
// 利用了如下的结论进行优化。
//基于已经计算出以 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月的每日一题了。😄
有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~