[Leetcode Weekly Contest]191

链接:LeetCode

[Leetcode]5424. 数组中两元素的最大乘积

给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)*(nums[j]-1) 取得最大值。
请你计算并返回该式的最大值。

由于均为正整数,故只要找出最大地两个数即可。

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        nums.sort()
        res = (nums[-1]-1) * (nums[-2]-1)
        return res

[Leetcode]5425. 切割后面积最大的蛋糕

矩形蛋糕的高度为 h 且宽度为 w,给你两个整数数组 horizontalCuts 和 verticalCuts,其中 (horizontalCuts[i])是从矩形蛋糕顶部到第  i 个水平切口的距离,类似地, (verticalCuts[j])是从矩形蛋糕的左侧到第 j 个竖直切口的距离。
请你按数组 horizontalCuts 和 verticalCuts 中提供的水平和竖直位置切割后,请你找出 面积最大 的那份蛋糕,并返回其 面积 。由于答案可能是一个很大的数字,因此需要将结果对 10^9 + 7 取余后返回。

如果知道切完后蛋糕的最大高度及宽度,那么就可以求得最大面积,排序求乘积即可。

class Solution:
    def maxArea(self, h: int, w: int, horizontalCuts: List[int], verticalCuts: List[int]) -> int:
        horizontalCuts = [0] + horizontalCuts + [h]
        verticalCuts = [0] + verticalCuts + [w]
        horizontalCuts.sort()
        verticalCuts.sort()
        res = self.getMaxGap(horizontalCuts) * self.getMaxGap(verticalCuts)
        return res%(10**9 + 7)

    def getMaxGap(self,nums):
        res = 0
        for i in range(1,len(nums)):
            res = max(res,nums[i]-nums[i-1])
        return res

[Leetcode]5426. 重新规划路线

n 座城市,从 0 到 n-1 编号,其间共有 n-1 条路线。因此,要想在两座不同城市之间旅行只有唯一一条路线可供选择(路线网形成一颗树)。去年,交通运输部决定重新规划路线,以改变交通拥堵的状况。
路线用 connections 表示,其中(connections[i] = [a, b])表示从城市 a 到 b 的一条有向路线。
今年,城市 0 将会举办一场大型比赛,很多游客都想前往城市 0 。
请你帮助重新规划路线方向,使每个城市都可以访问城市 0 。返回需要变更方向的最小路线数。
题目数据 保证 每个城市在重新规划路线方向后都能到达城市 0 。

记录入度与出度,通过BFS求解。

import collections
class Solution:
    def minReorder(self, n: int, connections: List[List[int]]) -> int:
        graph = collections.defaultdict(list)
        queue = deque()
        queue.append(0)
        res = 0
        visited = set([0])
        for u, v in connections:
            graph[u].append((v, 1))
            graph[v].append((u, 0))
        while queue:
            p = queue.pop()
            for node, flag in graph[p]:
                if node in visited: continue # 如果访问过就不管了
                res += flag
                queue.appendleft(node)
                visited.add(node)
        return res


[Leetcode]5427. 两个盒子中球的颜色数相同的概率

桌面上有 2n 个颜色不完全相同的球,球上的颜色共有 k 种。给你一个大小为 k 的整数数组 balls ,其中 balls[i] 是颜色为 i 的球的数量。
所有的球都已经 随机打乱顺序 ,前 n 个球放入第一个盒子,后 n 个球放入另一个盒子(请认真阅读示例 2 的解释部分)。
注意:这两个盒子是不同的。例如,两个球颜色分别为 a 和 b,盒子分别为 ([]) 和 (),那么 ([a] (b))([b] (a))这两种分配方式是不同的(请认真阅读示例 1 的解释部分)。
请计算「两个盒子中球的颜色数相同」的情况的概率。

DFS 遍历每一种颜色,需要在每一层保存当前的组合数(即有多少种可能的方式到达当前的状态),在遍历到该颜色时,假设该颜色有 nc 个球,可以取出的球的数量是 ([0, nc])。在这一层做循环,依次拿出 0 到 nc 个球,同时计算这种选择的组合数,和上一层组合数相乘,进入下一层。

class Solution:
    def getProbability(self, balls) -> float:
        # c1 是第一个箱子中的颜色数量,c2 是第二个箱子中的颜色数量
        c1, c2 = 0, 0
        # 所有的满足条件的取球的方式数量
        self.res = 0
        # 所有的取球的方式数量
        self.total = 0
        self.balls = balls
        self.target_count = sum(balls) // 2
        # 题目说明了每种颜色的球数量最大为 6,因此计算 0~6 的阶乘,后面直接查
        self.fact = [1] * 7
        for i in range(1, 7):
            self.fact[i] = self.fact[i-1]*i
        self.dfs(1, 0, 0, c1, c2)
        return self.res / self.total

    # choices: 到达这一层的状态时,所有可能的方式数量
    # counts: 已经取出来的球的数量
    # ball_idx:这一层要从哪种颜色里面取
    # c1: 第一个箱子中的颜色数量
    # c2: 第二个箱子中的颜色数量
    def dfs(self, choices, counts, ball_idx, c1, c2):
        # 如果取的球太多了,直接返回
        if counts > self.target_count:
            return
        # 如果取完了所有的颜色,判断两个箱子中的颜色数量是否相同
        if ball_idx == len(self.balls):
            if counts != self.target_count:
                return
            self.total += choices
            if c1 == c2:
                self.res += choices
            return
        # 这种颜色一共有多少球
        this_ball_num = self.balls[ball_idx]
        # 取出 i 个球放在第一个箱子,其余的放入第二个箱子
        for i in range(this_ball_num+1):
            c11 = c1+1 if i > 0 else c1
            c22 = c2+1 if i < this_ball_num else c2
            this_choice = self.fact[this_ball_num] / self.fact[i] / self.fact[this_ball_num-i]
            self.dfs(choices * this_choice, counts+i, ball_idx+1, c11, c22)


参考:
leetcode

原文地址:https://www.cnblogs.com/hellojamest/p/13021601.html