Python解题 - CSDN周赛第43期
Posted 请叫我问哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python解题 - CSDN周赛第43期相关的知识,希望对你有一定的参考价值。
感觉周赛越来越无趣了,基本都是考过的题目。上期周赛也是,4道题都曾考过,问哥也都写过题解,
奖品也不吸引人,实在没什么好写了。回想前段时间用力过猛,刷了C站大部分OJ题,以致于现在看到题目就直接套答案了。甚至于误打误撞,发现了周赛的测试链接,上了一次处罚名单。。。嗯(无辜脸)。。。
本期还是全部考过,除了第二题没写过题解,这里就把它补上吧。
第一题:判断胜负
已知两个字符串A,B。连续进行读入n次。每次读入的字符串都为A|B。输出读入次数最多的字符串。
分析
17期考过,可以参考问哥之前的题解。不过其实也没啥好解的,就是比较两个字符串哪个出现次数最多,平局就输出“dogfall”——顺便学个英文单词。
第二题:小豚鼠搬家
小豚鼠排排坐。 小艺酱买了一排排格子的小房子n*m,她想让k只小豚鼠每只小豚鼠都有自己的房子。 但是为了不浪费空间,她想要小房子的最外圈尽量每行每列都有一只小豚鼠居住(小豚鼠也可以住在中间的格子,只需保证房子最外围的行和列至少住一只豚鼠即可,无需每行每列都有豚鼠)。 小艺酱想知道自己有多少种方案安排小豚鼠。
输入描述:输入整数n,m,k。(1<=n,m<=20,0<=k<=n*m)
输出描述:输出方案数,答案对1e9+7取模。
示例:
输入 3 3 2 输出 2
分析
也曾在13期考过,但是网上靠谱的题解不多。
本题本质上就是排列组合,总共有 个格子,要放进去 只小豚鼠,如果不加任何限制的话,学过数学的都知道,总共有 种方案。但是题目要求最外面一圈的每行每列(实际上就是顶底两行与左右边两列)至少各有一只小豚鼠。在检查这个条件时,小豚鼠的数量可以重复计入。比如给的例子中,只有两只小豚鼠,于是只能这样放才能满足要求(也就是两种方案):
明白了题目的要求,我们可以先思考一下最朴素的穷举做法:先找出所有 种可能,然后逐一检查每种可能里,上、下、左、右四条边里有没有豚鼠。
这很容易,只要使用 python 内置的 combinations 函数,找出所有从坐标 到 的所有坐标中取出 个的组合,然后逐一检查其中是否存在横坐标为 和 ,以及纵坐标为 和 的坐标。
这种方法可以保证找到答案,但绝对会超时。因为我们其实并不关心每种方案的具体坐标有哪些,而只需要知道方案的数量。于是,我们拿总的方案数,减去不符合要求的方案不就可以了?
我们已知总的方案数是 ,那么不符合要求的有哪些方案呢?
- 一条边没有豚鼠:
- 顶边或底边没有豚鼠:
- 左边或右边没有豚鼠:
- 两条边没有豚鼠:
- 顶边和底边没有豚鼠:
- 左边和右边没有豚鼠:
- 顶边和左边、顶边和右边、底边和左边、底边和右边没有豚鼠:
- 三条边没有豚鼠:
- 顶边、左边、底边,或顶边、右边、底边没有豚鼠:
- 左边、顶边、右边,或左边、底边、右边没有豚鼠:
- 四条边没有豚鼠:
但是别急,当我们拿总数减去四次一条边没有豚鼠的情况的时候,实际上,我们重复减去了那些两条边、三条边的情况,所以我们要把两条边的情况加回来,但是这样一来,又重复加上了三条边的情况,所以还要将三条边的情况减去。。。所以,相信你也已经看出来了,实际上这题考察的又是容斥原理。
如果我们用 代表总的方案的集合, 各自代表上、下、左、右四条边上没有豚鼠的情况的集合,可以用数学公式表示如下:
一言以蔽之:将四种集合进行排列组合,如果组合中包含的集合个数是奇数,就减去,如果是偶数,就加上。
所以,回到我们这道题,结合我们刚才列出的所有情况,就可以得到答案如下:
代码就省略了吧,无非是用代码计算这个公式罢了。
第三题:醉酒的狱卒
某监狱有一个由n个牢房组成的大厅,每个牢房紧挨着。每个牢房里都有一个囚犯,每个牢房都是锁着的。一天晚上,狱卒感到无聊,决定玩一个游戏。在第一轮,他喝了一杯威士忌,然后跑下大厅,打开每个牢房的锁。在第二轮比赛中,他喝了一杯威士忌,然后跑下大厅,锁上每隔一个的牢房的锁(牢房2、4、6…)。在第三轮比赛中,他喝了一杯威士忌,然后跑下大厅。他每隔三个牢房(第3、6、9号牢房)就去一次。如果牢房被锁上了,他就把它打开;如果牢房门打开了,他就锁上牢房。他重复 n 轮,喝最后一杯,然后昏倒。一些囚犯(可能为零号)意识到他们的牢房被解锁且狱卒丧失了行动能力。他们就可以立即逃跑。现在根据牢房数量,确定有多少囚犯越狱。
分析
19期考过,题干很复杂,实际很简单。本题存在 的解法,可以参考问哥之前的题解。
第四题:会议安排
开会了!作为一个集体,开会的时候桌子当然是需要和老大相邻的!(老大可能坐在桌子上边) 小艺被分配到排桌椅的活,可是小艺的力气都用在吃上了,怎么可能搬动这些桌椅呢。 她决定用现有的布局当作是会议座位安排。每个桌子分配一个人。互相连接相同字符表示一个桌子,如UVV表示2张桌子,UVU则表示3张桌子。小艺想知道选择某个桌子之后老大身边能围多少人?
分析
20期考过,可以参考问哥之前写的题解。
关于字符串的处理,问哥一直觉得很麻烦,所以如果有更好的做法,还请告诉我,谢谢。
LeetCode周赛第193场周赛
一、5436. 一维数组的动态和:
给你一个数组 nums
。数组「动态和」的计算公式为:runningSum[i] = sum(nums[0]…nums[i])
。
请返回 nums
的动态和。
示例:
输入:nums = [1,2,3,4]
输出:[1,3,6,10]
解释:动态和计算过程为 [1, 1+2, 1+2+3, 1+2+3+4] 。输入:nums = [1,1,1,1,1]
输出:[1,2,3,4,5]
解释:动态和计算过程为 [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1] 。
分析:
? 一遍遍历即可。
代码(Python):
class Solution:
def runningSum(self, nums: List[int]) -> List[int]:
pre = 0
ans = []
for val in nums:
pre += val
ans.append(pre)
return ans
二、5437. 不同整数的最少数目:
给你一个整数数组 arr
和一个整数 k
。现需要从数组中恰好移除 k
个元素,请找出移除后数组中不同整数的最少数目。
示例:
输入:arr = [5,5,4], k = 1
输出:1
解释:移除 1 个 4 ,数组中只剩下 5 一种整数。输入:arr = [4,3,1,1,3,3,2], k = 3
输出:2
解释:先移除 4、2 ,然后再移除两个 1 中的任意 1 个或者三个 3 中的任意 1 个,最后剩下 1 和 3 两种整数。
分析:
? (1)首先需要对数组中元素进行计数,Python提供了基于哈希表实现的Counter。
? (2)接着就是排序加遍历,个数少的数优先-1,当个数为0时去除。
代码(Python):
class Solution:
def findLeastNumOfUniqueInts(self, arr: List[int], k: int) -> int:
counter = Counter(arr)
res = []
for key in counter:
res.append([key, counter[key]])
res.sort(key=lambda x: -x[1])
while k > 0:
res[-1][1] -= 1
k -= 1
if res[-1][1] == 0:
res.pop()
return len(res)
三、5438. 制作 m 束花所需的最少天数:
给你一个整数数组 bloomDay,以及两个整数 m 和 k 。
现需要制作 m 束花。制作花束时,需要使用花园中 相邻的 k 朵花 。
花园中有 n 朵花,第 i 朵花会在 bloomDay[i] 时盛开,恰好 可以用于 一束 花中。
请你返回从花园中摘 m 束花需要等待的最少的天数。如果不能摘到 m 束花则返回 -1 。
示例:
输入:bloomDay = [1,10,3,10,2], m = 3, k = 1
输出:3
解释:让我们一起观察这三天的花开过程,x 表示花开,而 _ 表示花还未开。
现在需要制作 3 束花,每束只需要 1 朵。
1 天后:[x, _, _, _, _] // 只能制作 1 束花
2 天后:[x, _, _, _, x] // 只能制作 2 束花
3 天后:[x, _, x, _, x] // 可以制作 3 束花,答案为 3输入:bloomDay = [1,10,3,10,2], m = 3, k = 2
输出:-1
解释:要制作 3 束花,每束需要 2 朵花,也就是一共需要 6 朵花。而花园中只有 5 朵花,无法满足制作要求,返回 -1 。
分析:
? (1)去重、排序:
? 由于题目给出的bloomDay数组中可能含有重复元素。并且题目需要我们返回最少的天数。因此提示我们还需要升序排序。因此我们可以先处理数据。
bloom_order = sorted(set(bloomDay))
? (2)遍历:
? 如果直接使用 for day in bloom_order:来进行排序,会超时。由于超过最小天数的天数也能够满足制作m束花的需求。因此满足二分的性质:单调性。因此可以使用二分查找来优化。
? (3)统计个数:
? 如果直接对每个位置都进行求取其后k个元素的值,会进行两层循环:
# O(N * k), 超时!!!
for i in range(len(bloomDay)):
for j in range(k):
# ...
? 还可以定义两个变量,分别保存可以制作的花的数量num,以及相邻k朵花中开放的花数量sums:
for i in range(len(bloomDay)):
if num >= m:
break
if bloomDay[i] <= day:
sum += 1
else:
sums = 0
if sums == k:
num += 1
sums = 0
return num >= m
代码(Python):
class Solution:
def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
def check(day):
num = sums = 0
for i in range(len(bloomDay)):
if num >= m:
break
if bloomDay[i] <= day:
sums += 1
else:
sums = 0
if sums == k:
num += 1
sums = 0
return num >= m
length = len(bloomDay)
if length < m * k:
return -1
bloom_order = sorted(set(bloomDay))
left, right = 0, len(bloom_order) - 1
while left <= right:
mid = (left + right) // 2
if check(bloom_order[mid]):
right = mid - 1
else:
left = mid + 1
return bloom_order[left]
四、1483. 树节点的第 K 个祖先:
给你一棵树,树上有 n 个节点,按从 0 到 n-1 编号。树以父节点数组的形式给出,其中 parent[i] 是节点 i 的父节点。树的根节点是编号为 0 的节点。
请你设计并实现 getKthAncestor(int node, int k) 函数,函数返回节点 node 的第 k 个祖先节点。如果不存在这样的祖先节点,返回 -1 。
树节点的第 k 个祖先节点是从该节点到根节点路径上的第 k 个节点。
示例:
输入:
["TreeAncestor","getKthAncestor","getKthAncestor","getKthAncestor"]
[[7,[-1,0,0,1,1,2,2]],[3,1],[5,2],[6,3]]输出:
[null,1,0,-1]解释:
TreeAncestor treeAncestor = new TreeAncestor(7, [-1, 0, 0, 1, 1, 2, 2]);treeAncestor.getKthAncestor(3, 1); // 返回 1 ,它是 3 的父节点
treeAncestor.getKthAncestor(5, 2); // 返回 0 ,它是 5 的祖父节点
treeAncestor.getKthAncestor(6, 3); // 返回 -1 因为不存在满足要求的祖先节点
分析:
? 看了官方题解。提到一种ACM的模板题解法——Binary Lifting。这里贴一个题解。之后遇到类似的题再仔细分析一下。
代码(Python):
class TreeAncestor:
def __init__(self, n: int, parent: List[int]):
self.cols = 20 # log(50000) < 20
self.dp = [[-1] * self.cols for _ in range(n)]
for i in range(n):
self.dp[i][0] = parent[i]
for j in range(1, self.cols):
for i in range(n):
if self.dp[i][j - 1] != -1:
self.dp[i][j] = self.dp[self.dp[i][j - 1]][j - 1]
return
def getKthAncestor(self, node: int, k: int) -> int:
for i in range(self.cols - 1, -1, -1):
if k & (1 << i):
node = self.dp[node][i]
if node == -1:
break
return node
# Your TreeAncestor object will be instantiated and called as such:
# obj = TreeAncestor(n, parent)
# param_1 = obj.getKthAncestor(node,k)
以上是关于Python解题 - CSDN周赛第43期的主要内容,如果未能解决你的问题,请参考以下文章