leetcode 周赛 173 - python 解答

5319. 删除回文子序列

题目

注意是子序列而不是子串!

所以只有三种可能的答案:

0:空串

1:整个字符串是回文串

2:不是回文串

class Solution:
    def removePalindromeSub(self, s: str) -> int:
        if not s: return 0
        def is_p(i, j):
            while i < j:
                if s[i] != s[j]:
                    return False
                i += 1
                j -= 1
            return True
        if is_p(0, len(s)-1): return 1
        return 2

5320. 餐厅过滤器

题目

简单

class Solution:
    def filterRestaurants(self, restaurants: List[List[int]], veganFriendly: int, maxPrice: int, maxDistance: int) -> List[int]:
        # restaurants[i] = [idi, ratingi, veganFriendlyi, pricei, distancei]
        ans = []
        for r in restaurants:
            if veganFriendly == 1 and r[2] == 0: continue
            if r[3] > maxPrice or r[4] > maxDistance: continue
            ans.append(r)
        ans.sort(key=lambda x: x[1]*1e5+x[0], reverse=True)
        return [x[0] for x in ans]

5321. 阈值距离内邻居最少的城市

题目

Floyd(弗洛伊德)算法

class Solution:
    def findTheCity(self, n: int, edges: List[List[int]], distanceThreshold: int) -> int:
        to = {}
        for i in range(n): 
            to[i] = {}
        for e in edges:
            if e[2] <= distanceThreshold:
                if e[1] in to[e[0]]:
                    to[e[0]][e[1]] = min(to[e[0]][e[1]], e[2])
                else:
                    to[e[0]][e[1]] = e[2]
                if e[0] in to[e[1]]:
                    to[e[1]][e[0]] = min(to[e[1]][e[0]], e[2])
                else:
                    to[e[1]][e[0]] = e[2]
        flag = True
        while flag:
            flag = False
            for c in to:
                tl = list(to[c].items())
                for d1, v1 in tl:
                    for d2, v2 in to[d1].items():
                        if d2 == c: continue
                        if v1 + v2 <= distanceThreshold:
                            if d2 in to[c]:
                                if v2 + v1 < to[c][d2]:
                                    flag = True
                                    to[c][d2] = v1 + v2
                            else:
                                to[c][d2] = v1 + v2
                                flag = True
        mc = n + 1
        mid = -1
        for c in to:
            if len(to[c]) == mc and c > mid or len(to[c]) < mc:
                mc = len(to[c])
                mid = c
        return mid

5322 工作计划的最低难度

题目

题目概括

n 个工作,d 天,每天完成一个或多个工作,每日工作量是当日工作量最大的一个工作的值。工作必须顺序执行。

求:d 天完成所有工作最小工作量的和

解法

二维数组 dp[i][j] 代表使用 i 天完成 j 个工作的最小工作量。(注意 dp 数组的第一列和第一行,也就是下标 0,是没有用的,也没有意义)

状态转移

首先只有 j >= i 的时候才有解,否则返回 -1

所以要求的是 i 天里工作数从 i 到 n。

i 天做 j 个工作。可以是前 i - 1 天做了前 k 个工作,最后一天做了 剩余所有的工作(最后一天的工作量是:k 到 j 的最大值),所以

dp[i][j] = dp[i-1][j-1] + jobDifficulty[j-1] # 初始化成前 i-1 天做了 j-1 个工作,最后一天做最后一个工作
work = jobDifficulty[j-1] # work 是 k 到 j 的最大值
for k in range(j-2, i-2, -1):
    work = max(jobDifficulty[k], work)
    if dp[i-1][k] + work < dp[i][j]: # i-1 天做前 k 个工作,最后一天做 k 到 j 的工作。
        dp[i][j] = dp[i-1][k] + work

初始化

初始化 1 天完成 1 个任务,2 个任务 ..... n 个任务。工作量自然就是这些任务中的最大值。

for i in range(2, jc+1):
    dp[1][i] = max(dp[1][i-1], jobDifficulty[i-1])

代码

class Solution:
    def minDifficulty(self, jobDifficulty: List[int], d: int) -> int:
        jc = len(jobDifficulty)
        if d > jc: return -1
        dp = [[-1 for i in range(jc+1)] for i in range(d+1)]
        dp[1][1] = jobDifficulty[0]

        for i in range(2, jc+1):
            dp[1][i] = max(dp[1][i-1], jobDifficulty[i-1])
        
        for i in range(2, d+1):
            for j in range(i, jc+1):
                dp[i][j] = dp[i-1][j-1] + jobDifficulty[j-1]
                work = jobDifficulty[j-1]
                for k in range(j-2, i-2, -1):
                    work = max(jobDifficulty[k], work)
                    if dp[i-1][k] + work < dp[i][j]:
                        dp[i][j] = dp[i-1][k] + work
        return dp[d][jc]

欢迎来我的博客: https://codeplot.top/
我的博客刷题分类:https://codeplot.top/categori...

你可能感兴趣的:(python,leetcode)