LeetCode笔记:Biweekly Contest 77

1. 题目一

给出题目一的试题链接如下:

1. 解题思路

这一题思路还是比较直接的,就是直接统计一下所有的前缀字符,然后看一下words当中各个前缀字符出现的频次,然后相加即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def countPrefixes(self, words: List[str], s: str) -> int:
        cnt = Counter(words)
        n = len(s)
        res = 0
        for i in range(n):
            res += cnt[s[:i+1]]
        return res

提交代码评测得到:耗时79ms,占用内存14.1MB。

2. 题目二

给出题目二的试题链接如下:

1. 解题思路

这一题思路上很直接,就是遍历一下每一个位置求解一下了均值之差。

而关于均值的计算,可以通过一个累积数组进行效率优化。

2. 代码实现

给出python代码实现如下:

class Solution:
    def minimumAverageDifference(self, nums: List[int]) -> int:
        s = sum(nums)
        n = len(nums)
        diff = s // n
        res = n-1
        t = 0
        for i in range(n-1):
            t += nums[i]
            tmp = abs(t // (i+1) - (s-t) // (n-i-1))
            if tmp < diff or (tmp == diff and res == n-1):
                res = i
                diff = abs(t // (i+1) - (s-t) // (n-i-1))
        return res

提交代码评测得到:耗时1017ms,占用内存24.9MB。

3. 题目三

给出题目三的试题链接如下:

1. 解题思路

这一题依然还是一个累积数组的思路,就是在上下左右4个方向上,分别通过守卫的位置计算出能够被覆盖到的位置,然后合并4个方向上的情况,就能够最终得到守卫覆盖情况。

2. 代码实现

给出python代码实现如下:

class Solution:
    def countUnguarded(self, m: int, n: int, guards: List[List[int]], walls: List[List[int]]) -> int:
        status = [[0 for _ in range(n)] for _ in range(m)]
        for i, j in guards:
            status[i][j] = 1
        for i, j in walls:
            status[i][j] = -1
            
        l2r = [[0 for _ in range(n)] for _ in range(m)]
        for i in range(m):
            l2r[i][0] = 0 if status[i][0] != 1 else 1
            for j in range(1, n):
                if status[i][j] == -1:
                    l2r[i][j] = 0
                else:
                    l2r[i][j] = l2r[i][j-1] + status[i][j]
                
        r2l = [[0 for _ in range(n)] for _ in range(m)]
        for i in range(m):
            r2l[i][n-1] = 0 if status[i][n-1] != 1 else 1
            for j in range(n-2, -1, -1):
                if status[i][j] == -1:
                    r2l[i][j] = 0
                else:
                    r2l[i][j] = r2l[i][j+1] + status[i][j]
                    
        t2b = [[0 for _ in range(n)] for _ in range(m)]
        for j in range(n):
            t2b[0][j] = 0 if status[0][j] != 1 else 1
            for i in range(1, m):
                if status[i][j] == -1:
                    t2b[i][j] = 0
                else:
                    t2b[i][j] = t2b[i-1][j] + status[i][j]
                    
        b2t = [[0 for _ in range(n)] for _ in range(m)]
        for j in range(n):
            b2t[m-1][j] = 0 if status[m-1][j] != 1 else 1
            for i in range(m-2, -1, -1):
                if status[i][j] == -1:
                    b2t[i][j] = 0
                else:
                    b2t[i][j] = b2t[i+1][j] + status[i][j]
        
        res = [(i, j) for i in range(m) for j in range(n) if status[i][j] != -1 and l2r[i][j] + r2l[i][j] + t2b[i][j] + b2t[i][j] == 0]
        return len(res)

提交代码评测得到:耗时5340ms,占用内存76.7MB。

4. 题目四

给出题目四的试题链接如下:

1. 解题思路

这一题我的思路是分别计算火蔓延到每个位置所需要的时间和人跑到每一个位置上所需要的最短时间。

如果火蔓延截断了必经路线的时间短于人跑到这个位置的最短时间,那么人就无法逃离,反之,如果大于,那么这个时间差就是针对这个路线能够等待的最长时间。

唯一需要注意的是,这里有一个比较特殊的位置,就是安全屋的位置,只有这个地方可以使得等待时间+1,因此只有这个位置可以允许人和火在同一时间到达。

2. 代码实现

给出python代码实现如下:

class Solution:
    def maximumMinutes(self, grid: List[List[int]]) -> int:
        n, m = len(grid), len(grid[0])
        times = [[0 for _ in range(m)] for _ in range(n)]
        seen = {(0, 0)}
        q = [(0, 0, 0)]
        while q:
            t, i, j = q.pop(0)
            times[i][j] = t
            if i == n-1 and j == m-1:
                break
            if (i-1, j) not in seen and i-1 >= 0 and grid[i-1][j] == 0:
                q.append((t+1, i-1, j))
                seen.add((i-1, j))
            if (i+1, j) not in seen and i+1 < n and grid[i+1][j] == 0:
                q.append((t+1, i+1, j))
                seen.add((i+1, j))
            if (i, j-1) not in seen and j-1 >= 0 and grid[i][j-1] == 0:
                q.append((t+1, i, j-1))
                seen.add((i, j-1))
            if (i, j+1) not in seen and j+1 < m and grid[i][j+1] == 0:
                q.append((t+1, i, j+1))
                seen.add((i, j+1))
        if times[-1][-1] == 0:
            return -1
        
        cnt = defaultdict(int)
        for i in range(n):
            for j in range(m):
                if times[i][j] != 0:
                    cnt[times[i][j]] += 1
        cnt[times[i][j]] = 1

        fires = [[0 for _ in range(m)] for _ in range(n)]
        q = [(0, i, j) for i in range(n) for j in range(m) if grid[i][j] == 1]
        seen = {(i, j) for i in range(n) for j in range(m) if grid[i][j] == 1}
        res = 1000000000
        while q:
            t, i, j = q.pop(0)
            fires[i][j] = t
            if times[i][j] != 0 and times[i][j] <= times[-1][-1]:
                if times[i][j] != times[-1][-1] or (i == n-1 or j == m-1):
                    cnt[times[i][j]] -= 1
                    if cnt[times[i][j]] == 0:
                        if i == n-1 and j == m-1:
                            if t - times[i][j] >= 0:
                                res = min(res, t - times[i][j])
                            else:
                                return -1
                        else:   
                            if t - times[i][j] - 1 >= 0:
                                res = min(res, t - times[i][j] - 1)
                            else:
                                return -1
            if (i-1, j) not in seen and i-1 >= 0 and grid[i-1][j] == 0:
                q.append((t+1, i-1, j))
                seen.add((i-1, j))
            if (i+1, j) not in seen and i+1 < n and grid[i+1][j] == 0:
                q.append((t+1, i+1, j))
                seen.add((i+1, j))
            if (i, j-1) not in seen and j-1 >= 0 and grid[i][j-1] == 0:
                q.append((t+1, i, j-1))
                seen.add((i, j-1))
            if (i, j+1) not in seen and j+1 < m and grid[i][j+1] == 0:
                q.append((t+1, i, j+1))
                seen.add((i, j+1))
        return res

提交代码评测得到:耗时492ms,占用内存17.4MB。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值