1377. Frog Position After T Seconds (H)

Frog Position After T Seconds (H)

Given an undirected tree consisting of n vertices numbered from 1 to n. A frog starts jumping from the vertex 1. In one second, the frog jumps from its current vertex to another unvisited vertex if they are directly connected. The frog can not jump back to a visited vertex. In case the frog can jump to several vertices it jumps randomly to one of them with the same probability, otherwise, when the frog can not jump to any unvisited vertex it jumps forever on the same vertex.

The edges of the undirected tree are given in the array edges, where edges[i] = [fromi, toi] means that exists an edge connecting directly the vertices fromi and toi.

Return the probability that after t seconds the frog is on the vertex target.

Example 1:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5mXPwXQM-1583705622409)(assets/frog_2.png)]

Input: n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 2, target = 4
Output: 0.16666666666666666 
Explanation: The figure above shows the given graph. The frog starts at vertex 1, jumping with 1/3 probability to the vertex 2 after second 1 and then jumping with 1/2 probability to vertex 4 after second 2. Thus the probability for the frog is on the vertex 4 after 2 seconds is 1/3 * 1/2 = 1/6 = 0.16666666666666666. 

Example 2:

**[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1YhcBu0s-1583705622411)(assets/frog_3.png)]**

Input: n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 1, target = 7
Output: 0.3333333333333333
Explanation: The figure above shows the given graph. The frog starts at vertex 1, jumping with 1/3 = 0.3333333333333333 probability to the vertex 7 after second 1. 

Example 3:

Input: n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 20, target = 6
Output: 0.16666666666666666

Constraints:

  • 1 <= n <= 100
  • edges.length == n-1
  • edges[i].length == 2
  • 1 <= edges[i][0], edges[i][1] <= n
  • 1 <= t <= 50
  • 1 <= target <= n
  • Answers within 10^-5 of the actual value will be accepted as correct.

题意

给定一个无向图,一个🐸从结点1开始跳,必须跳t下,每一次跳向邻近点的概率都是相同的,且不能往回跳,无路可跳时则原地跳,问该🐸最后停在指定的结点处的概率。

思路

首先要注意这实际上是一张图而不是以1为根结点的树。

两种方法:

  1. 利用BFS从结点1开始向外走t层,记录下到达每个结点的概率;
  2. 也可以利用DFS找到目标节点,在寻找过程中生成路径(即 到达点->出发点),最后统计从结点1走到目标结点的概率。

代码实现 - BFS

class Solution {
    public double frogPosition(int n, int[][] edges, int t, int target) {
        // 生成图
        List<List<Integer>> graph = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
            graph.add(new ArrayList<>());
        }
        for (int[] edge : edges) {
            graph.get(edge[0]).add(edge[1]);
            graph.get(edge[1]).add(edge[0]);
        }

        // BFS处理
        boolean[] visited = new boolean[n + 1];
        Queue<Integer> q = new LinkedList<>();
        double[] prob = new double[n + 1];
        q.offer(1);
        visited[1] = true;
        prob[1] = 1;
        while (!q.isEmpty() && t-- > 0) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int u = q.poll();
                int neighbors = 0;
                for (int v : graph.get(u)) {
                    if (!visited[v]) {
                        neighbors++;
                    }
                }
                for (int v : graph.get(u)) {
                    if (!visited[v]) {
                        visited[v] = true;
                        q.offer(v);
                        prob[v] = prob[u] / neighbors;
                    }
                }
                // 还需继续跳且存在可以跳的结点时,一定不会停留在当前结点
                if (neighbors != 0) {
                    prob[u] = 0;
                }
            }
        }
        return prob[target];
    }
}

代码实现 - DFS

class Solution {
    public double frogPosition(int n, int[][] edges, int t, int target) {
        // 生成图
        List<List<Integer>> graph = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
            graph.add(new ArrayList<>());
        }
        for (int[] edge : edges) {
            graph.get(edge[0]).add(edge[1]);
            graph.get(edge[1]).add(edge[0]);
        }

        // dfs处理
        int[] prev = new int[n + 1];
        boolean[] visited = new boolean[n + 1];
        visited[1] = true;
        int len = dfs(1, target, graph, prev, visited);
        // 存在以下情况可以判断无法停在target:
        // 1. 跳跃的次数小于1到target的长度
        // 2. 跳跃次数大于1到target的长度且还存在可以跳的结点
        if (t < len || t > len && (target == 1 && graph.get(1).size() > 0 || graph.get(target).size() > 1)) {
            return 0;
        }
        // 累乘得到从结点1走到target的概率的分母
        int denominator = 1;
        while (prev[target] != 0) {
            target = prev[target];
            denominator *= target == 1 ? graph.get(1).size() : graph.get(target).size() - 1;
        }
        
        return 1.0 / denominator;
    }

    // 返回从u到target的长度,无法到达则返回-1
    private int dfs(int u, int target, List<List<Integer>> graph, int[] prev, boolean[] visited) {
        if (u == target) {
            return 0;
        }

        for (int v : graph.get(u)) {
            if (!visited[v]) {
                visited[v] = true;
                prev[v] = u;
                int len = dfs(v, target, graph, prev, visited);
                if (len >= 0) {
                    return 1 + len;
                }
            }
        }

        return -1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值