leetcode 周賽 173 - python 解答

5319. 刪除迴文子序列

題目python

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

因此只有三種可能的答案:數組

0:空串app

1:整個字符串是迴文串rest

2:不是迴文串code

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. 餐廳過濾器

題目ci

簡單leetcode

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. 閾值距離內鄰居最少的城市

題目rem

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...

相關文章
相關標籤/搜索