[Leetcode Weekly Contest]174

链接:LeetCode

[Leetcode]5328. 方阵中战斗力最弱的 K 行

给你一个大小为 m * n 的方阵 mat,方阵由若干军人和平民组成,分别用 0 和 1 表示。
请你返回方阵中战斗力最弱的 k 行的索引,按从最弱到最强排序。
如果第 i 行的军人数量少于第 j 行,或者两行军人数量相同但 i 小于 j,那么我们认为第 i 行的战斗力比第 j 行弱。
军人 总是 排在一行中的靠前位置,也就是说 1 总是出现在 0 之前。

输入:\(mat = [[1,1,0,0,0], [1,1,1,1,0], [1,0,0,0,0], [1,1,0,0,0], [1,1,1,1,1]], k = 3\)
输出:\([2,0,3]\)

按照题意排序即可。

class Solution:
    def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:
        res = []
        n,m = len(mat),len(mat[0])
        for i in range(n):
            num = len([x for x in mat[i] if x==1])
            res.append([i,num])
        res.sort(key=lambda x:[x[1],x[0]])
        return [x[0] for x in res][:k]

[Leetcode]5329. 数组大小减半

给你一个整数数组 arr。你可以从中选出一个整数集合,并删除这些整数在数组中的每次出现。
返回至少能删除数组中的一半整数的整数集合的最小大小。
统计每个数出现的次数,然后排序即可。

import collections
class Solution:
    def minSetSize(self, arr: List[int]) -> int:
        count = collections.Counter(arr)
        num = sorted(count.values())
        res = 0
        all_del = 0
        for n in num[::-1]:
            all_del+=n
            res += 1
            if all_del>=len(arr)//2:
                return res

[Leetcode]5330. 分裂二叉树的最大乘积

给你一棵二叉树,它的根为 root 。请你删除 1 条边,使二叉树分裂成两棵子树,且它们子树和的乘积尽可能大。由于答案可能会很大,请你将结果对 10^9 + 7 取模后再返回。
要计算子树和的乘积,不如只计算一个子树的和,然后将二叉树所有和减去该树即可得另一个字数和。如此,我们只需要计算每一个字数的和,从中选取一个能组成最大子树和乘积即可。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def maxProduct(self, root: TreeNode) -> int:
        res = 0
        dic = {}
        all_sum = self.dfs(root,dic)
        for val in dic.values():
            res = max(res,val*(all_sum-val))
        return res%(10**9 + 7)

    def dfs(self,root,dic):
        if not root:
            return 0
        if not root.left and not root.right:
            dic[root] = root.val
        else:
            dic[root] = root.val + self.dfs(root.left,dic) + self.dfs(root.right,dic)
        return dic[root]

[Leetcode]5331. 跳跃游戏 V

给你一个整数数组 arr 和一个整数 d 。每一步你可以从下标 i 跳到:

  • i + x ,其中 i + x < arr.length 且 0 < x <= d 。
  • i - x ,其中 i - x >= 0 且 0 < x <= d 。

除此以外,你从下标 i 跳到下标 j 需要满足:arr[i] > arr[j] 且 arr[i] > arr[k] ,其中下标 k 是所有 i 到 j 之间的数字(更正式的,min(i, j) < k < max(i, j))。
你可以选择数组的任意下标开始跳跃。请你返回你最多可以访问多少个下标。

利用动态规划的思想,令dp[i]为从位置i开始所能访问的最大下标数,则动态规划的递推式为:
\(dp[i] = max(dp[i],dp[j]+1)\),其中j为位置i可达点的下标。
其实,想出动态规划的递推式不难,关键在于我们怎么保证在计算dp[i]时,dp[j]可知。明显的,在数组中,我们在最低的点没有办法进行跳跃,则从该索引i出发最多访问1个下标;那么,我们再从第二低的点出现,此时,该点要么无法跳跃,要么只能跳最低的点,而此时\(dp[i]=1\)。由此可知,我们将整个数组从最小值开始遍历,到最大值,即可保证为全局最佳解。而这,与我们平时的从左到右的遍历不同,也是该问题的关键点了。

class Solution:
    def maxJumps(self, arr, d) :
        index_num = list(enumerate(arr))
        index_num.sort(key = lambda x:x[1])
        n = len(arr)
        dp = [1 for i in range(n)]
        res = 1
        for index,num in index_num:
            for i in reversed(range(max(0,index-d),index)):
                if arr[i] >= num:
                    break
                dp[index] = max(dp[index],dp[i]+1)
            for i in range(index+1,min(index+d+1,n)):
                if arr[i] >= num:
                    break
                dp[index] = max(dp[index],dp[i]+1)
            res = max(res,dp[index])
        return res

你可能感兴趣的:([Leetcode Weekly Contest]174)