leetcode-T秒后青蛙的位置

 题目是LeetCode第179场周赛的第四题,链接:T秒后青蛙的位置。问题较长就不搬运了,详见原题描述。这道题是hard难度的,当时周赛时只把前三题做了,这道题也是后来才做的,不过后来做倒是让我想出来了一个时间上超过了100%的方法,java版代码只需要1ms。

 类似周赛第三题,同样可以采用建树然后DFS的方法,不过对于这道题,还是可以用更加简便的从底到顶的方法。

 首先需要说明一下这道题数据的特殊性,以1为根节点所构造出来的树,其子节点的值一定是比父节点大的,而且因为只有n-1条边从而不存在环。也就是说,每个节点只可能有一个父节点(当然子节点的数目就不限了)。

 基于以上观察,我们使用一个数组father记录各个节点的父节点,另一个数组sonNum记录各个节点的子节点数目。

 那么怎么计算概率呢,其实很简单,我们从idx=target出发,一直沿着父节点father[idx]往上走(循环使用idx=father[idx]),当到达根节点(father[idx]==0)时就得到了唯一可能的一条路径,这条路径上各个父节点的子节点数目为sonNum[father[idx]],概率的计算就是将所有的1/sonNum[father[idx]]乘起来就是了。

 但是需要注意的是可以返回此概率的情况,假设此路径一共经过count次跳转(其实就是边数=节点数-1),那么只有当t==count(跳转次数刚好等于秒数)或者count < t && targetCount == 1 && target != 1(秒数大于跳转次数,此时需要目标节点为叶子节点,才能在target上原地踏步),其他情况都是直接返回0。

 复杂度分析:初始化fathersonNum需要时间复杂度 O ( N ) O(N) O(N),计算概率需要的时间复杂度为树的高度,最坏情况为只有左节点或右节点且target为叶子节点的情况,此时时间复杂度为 O ( N ) O(N) O(N)。因此总的时间复杂度为 O ( N ) O(N) O(N)。空间复杂度就是几个辅助数组所占用空间,所以为 O ( N ) O(N) O(N)

 JAVA版代码如下:

class Solution {
    public double frogPosition(int n, int[][] edges, int t, int target) {
        if (n == 1) {
            return target == 1 && t >= 1 ? 1.0 : 0.0;
        }
        int[] father = new int[n + 1];
        int[] sonNum = new int[n + 1];
        int targetCount = 0;
        for (int i = 0; i < n - 1; ++i) {
            if (edges[i][0] < edges[i][1]) {
                ++sonNum[edges[i][0]];
                father[edges[i][1]] = edges[i][0];
            }
            else {
                ++sonNum[edges[i][1]];
                father[edges[i][0]] = edges[i][1];
            }
            if (edges[i][0] == target || edges[i][1] == target) {
                ++targetCount;
            }
        }

        double probability = 1.0;
        int count = 0;
        int idx = target;
        while (father[idx] > 0) {
            probability /= sonNum[father[idx]];
            idx = father[idx];
            ++count;
        }
        if ((count < t && targetCount == 1 && target != 1) || count == t) {
            return probability;
        } 
        return 0.0;
    }
}

 提交结果如下:


 Python版代码如下:

class Solution:
    def frogPosition(self, n: int, edges: List[List[int]], t: int, target: int) -> float:
        if n == 1:
            return 1.0 if target == 1 and t >= 1 else 0.0
        father = [0 for _ in range(n + 1)]
        sonNum = father.copy()
        targetCount = 0
        for i, j in edges:                  #初始化各节点父节点,以及各节点的子节点数目
            if i < j:
                father[j] = i
                sonNum[i] += 1
            else:
                father[i] = j
                sonNum[j] += 1
            if i == target or j == target:  #统计target节点出现次数
                targetCount += 1
        idx = father[target]
        count = 0
        probability = 1.0
        while idx != 0:                     #从target往上走直到节点1
            count += 1                      #统计跳转次数(也即边数)
            probability /= sonNum[idx]      #计算从target到节点1的总概率
            idx = father[idx]
        #可以返回概率的情况:要么target节点是叶子节点,要么跳转次数刚好等于秒数t
        if (count < t and targetCount == 1 and target != 1) or count == t:
            return probability
        else:
            return 0.0

 提交结果如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值