【每日一题】T 秒后青蛙的位置

1377. T 秒后青蛙的位置

关键词:深度优先

题目来源:1377. T 秒后青蛙的位置 - 力扣(Leetcode)

题目描述
 T深度优先

给你一棵由 n 个顶点组成的无向树,顶点编号从 1 到 n。青蛙从 顶点 1 开始起跳。规则如下:

  • 在一秒内,青蛙从它所在的当前顶点跳到另一个 未访问 过的顶点(如果它们直接相连)。
  • 青蛙无法跳回已经访问过的顶点。
  • 如果青蛙可以跳到多个不同顶点,那么它跳到其中任意一个顶点上的机率都相同。
  • 如果青蛙不能跳到任何未访问过的顶点上,那么它每次跳跃都会停留在原地。

无向树的边用数组 edges 描述,其中 edges[i] = [fromi, toi] 意味着存在一条直接连通 fromitoi 两个顶点的边。

返回青蛙在 t 秒后位于目标顶点 target 上的概率。

输入:n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 2, target = 4
输出:0.16666666666666666 
输入:n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 1, target = 7
输出:0.3333333333333333
数据范围
1 <= n <= 100
edges.length == n - 1
edges[i].length == 2
1 <= ai, bi <= n
1 <= t <= 50
1 <= target <= n
问题分析

无向树的起点为1,且青蛙不能往回跳,故题目所说的无向树实际上是一棵有向树。

依题意,当时间为t时,若青蛙能位于target,则概率不为0,否则概率为0。故存在以下两种情况概率不为0:

  • 时间为t,且青蛙恰好位于target
  • 时间小于t,但t为叶子结点,故可原地跳,则时间为t时,青蛙可位于target

于是,题目等价于判断是否存在以上两种情况。

每跳一次,花费时间为1,故t可看做深度限制,根节点1的深度为0。

由于要计算概率,每个结点只能跳到其子结点,故需要统计每个点的子结点的数量。

对于此类有关树的搜索问题,显然可以采用深搜来求解。采用深搜时,可做如下优化

  • 当搜索到结点target时,结果是可以确定的
  • 当深度大于t时,不必继续往下搜索,可直接返回。
代码实现
double frogPosition(int n, vector<vector<int>> &edges, int t, int target) {
    memset(h, -1, sizeof h);
    memset(cnt, -1, sizeof cnt);
    // 预处理
    for (const auto &v: edges) {
        add(v[0], v[1]), add(v[1], v[0]);
        cnt[v[0]]++, cnt[v[1]]++;
    }
    cnt[1]++;
    // 深搜
    int res = 0;
    function<int(int, int, int, int)> dfs = [&](int u, int p, int d, int pro) {
        // 找到目标顶点:结果确定
        if (u == target) {
            res = pro;
            // 时间刚好或没到时间但可原地踏步则说明存在概率
            return (d == t || d < t && !cnt[u]) ? 1 : -1;
        }
        // 未找到目标顶点但时间已过:结果未定
        if (d >= t)return 0;
        for (int i = h[u], r; ~i; i = ne[i]) {
            if (e[i] == p) continue;
            r = dfs(e[i], u, d + 1, pro * cnt[u]);
            // 结果已定:返回
            if(r)return r;
        }
        // 结果未定:继续
        return 0;
    };
    int r = dfs(1, -1, 0, 1);
    if(r==1)return 1.0 / res;
    return 0;
}

时间复杂度:O(n)

空间复杂度:O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值