自学内容网 自学内容网

LeetCode 第 425 场周赛 个人题解

Q1. 最小正和子数组

原题链接

Q1. 最小正和子数组

思路分析

签到题,暴力就行

时间复杂度:O(N^2)

AC代码
class Solution:
    def minimumSumSubarray(self, nums: List[int], l: int, r: int) -> int:
        n = len(nums)
        res = -1

        acc = list(accumulate(nums, initial=0))
        
        for i in range(n):
            for j in range(i + l - 1, min(n, i + r)):
                if  acc[j + 1] - acc[i] > 0:
                    if res == -1:
                        res = acc[j + 1] - acc[i]
                    else:
                        res = min(res, acc[j + 1] - acc[i])
                

        return res

Q2. 重排子字符串以形成目标字符串

原题链接

Q2. 重排子字符串以形成目标字符串

思路分析

存一下s中每个块的数目和t的每个块比对下数量够不够

时间复杂度:O(N)

AC代码
class Solution:
    def isPossibleToRearrange(self, s: str, t: str, k: int) -> bool:
        cnt = Counter()
        n, m = len(s), len(t)
        if n % k: return False
        B = n // k
        for i in range(0, n, B):
            cnt[s[i:i+B]] += 1
        for i in range(0, m, B):
            if cnt[t[i:i+B]] == 0:
                return False
            cnt[t[i:i+B]] -= 1
        return True

Q3. 最小数组和

原题链接

Q3. 最小数组和

思路分析

很典的dp

f(i, j, k) 为 [i, n - 1] 剩余 j 次 操作1,k次操作2的最小数组和

枚举当前的方案进行转移即可

时间复杂度:O(N OP1 OP 2)

AC代码
class Solution:
    def minArraySum(self, nums: List[int], v: int, op1: int, op2: int) -> int:
        n = len(nums)
        @cache
        def dfs(i: int, j: int, k: int):
            if i == n: return 0
            res = nums[i] + dfs(i + 1, j, k)
            if j:
                res = min(res, (nums[i] + 1) // 2 + dfs(i + 1, j - 1, k))
            if k and nums[i] >= v:
                res = min(res, nums[i] - v + dfs(i + 1, j, k - 1))
            if j and k and nums[i] >= v:
                t = (nums[i] - v + 1) // 2
                if (nums[i] + 1) // 2 >= v:
                    t = min(t, (nums[i] + 1) // 2 - v)
                
                res = min(res, t + dfs(i + 1, j - 1, k - 1))

            return res
        res = dfs(0, op1, op2)
        dfs.cache_clear()
        return res

Q4. 移除边之后的权重最大和

原题链接

Q4. 移除边之后的权重最大和

思路分析

树形dp + 贪心

每个边选或不选,容易想到树上背包

但是这个数据量,显然会炸掉,尝试优化

定义 f(u, lim) 为 u 所在子树最大合法化值,lim = true 说明<p, u> 的边被父节点拿掉了,否则没拿掉

所以 u 能够保存的边数目为 min(k - lim, adj[u] - 1)

我们假设 u 往下伸的所有边 都不拿,然后贪心的考虑拿谁

一条边 <u, v> 从不拿到拿的变化花费:f(v, true) + w - f(v, false)

即,按照f(v, true) + w - f(v, false) 从大到小拿即可

时间复杂度:O(nlogm)

AC代码
class Solution:
    def maximizeSumOfWeights(self, edges: List[List[int]], k: int) -> int:
        n = len(edges) + 1
        adj = [[] for _ in range(n)]
        
        for (u, v, w) in edges:
            adj[u].append([v, w])
            adj[v].append([u, w])

        @cache
        def dfs(u: int, p: int, lim: bool) -> int:
            t = k - lim
            h = []
            res = 0
            for (v, w) in adj[u]:
                if v == p: continue
                a = dfs(v, u, False)
                b = w + dfs(v, u, True)
                h.append(b - a)
                res += a

            h.sort(reverse=True)
            for i in range(min(t, len(h))):
                if h[i] <= 0: break
                res += h[i]
                
            return res
            
        return dfs(0, -1, False)


原文地址:https://blog.csdn.net/EQUINOX1/article/details/144005749

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!