这次周赛有点问题,第三题 5334.推文计数 先是出现了在线测试 500 错误。之后提交的时候有些答案错误的情况,系统会返回一个对不上的输入,导致查找错误很困难,也让人很困惑,但是实际上代码对了应该是能过的,我是比赛后才过的。
5332. 检查整数及其两倍数是否存在
https://leetcode-cn.com/probl...
https://leetcode-cn.com/conte...
解题思路
这题居然错了两次。第一次使用 set,结果无法处理 0 的情况,于是换用了 collections.Counter 因为对于 0 要统计 0 的数量,虽然 0 的 2 倍仍然是 0 本身,但是只有 1 个 0 仍是不行的。
代码
class Solution:
def checkIfExist(self, arr: List[int]) -> bool:
import collections
s = collections.Counter(arr)
for n in s:
if n == 0:
if s[n] > 1: return True
elif n<<1 in s:
return True
return False
5333.制造字母异位词的最小步骤数
https://leetcode-cn.com/conte...
https://leetcode-cn.com/probl...
解题思路
使用两个 Counter 分别统计 s 和 t 中出现的各个字母的数量。
只看 t 中比 s 多的字母,一共多多少,加起来就是答案
代码
class Solution:
def minSteps(self, s: str, t: str) -> int:
import collections
c1 = collections.Counter(s)
c2 = collections.Counter(t)
ans = 0
for c in c2:
if c not in c1:
ans += c2[c]
else:
if c2[c] > c1[c]:
ans += c2[c] - c1[c]
return ans
1348. 推文计数
https://leetcode-cn.com/probl...
https://leetcode-cn.com/conte...
解题思路
比赛的时候样例返回有问题。
本身不难,维护一个字典,把每个用户的时间放入一个数组,查询时,先排序,然后二分找到起始点,向后遍历,要注意的是,如果后面的时间范围中没有推文,也要往数组里补充相应数量的 0。
代码
import bisect
class TweetCounts:
def __init__(self):
self.ul = {}
def recordTweet(self, tweetName: str, time: int) -> None:
if tweetName not in self.ul: self.ul[tweetName] = []
self.ul[tweetName].append(time)
def getTweetCountsPerFrequency(self, freq: str, tweetName: str, startTime: int, endTime: int) -> List[int]:
self.ul[tweetName].sort()
#print(self.ul[tweetName])
if freq == 'minute':
f = 60
elif freq == 'hour':
f = 3600
else:
f = 86400
b = bisect.bisect(self.ul[tweetName], startTime-1)
ans = []
cnt = 0
limit = startTime + f
for n in self.ul[tweetName][b:]:
#print(n)
if n > endTime:
ans.append(cnt)
r = (endTime - limit) // f
if limit < endTime:
ans.append(0)
if r > 0:
ans += [0] * r
return ans
if n >= limit:
# 0-59 60-119
ans.append(cnt)
r = (n - limit) // f
if r > 0:
ans += [0] * r
limit += (r + 1) * f
cnt = 0
cnt += 1
ans.append(cnt)
if limit < endTime:
ans.append(0)
r = (endTime - limit) // f
#print(r, limit)
if r > 0:
ans += [0] * r
return ans
5335.参加考试的最大学生数
https://leetcode-cn.com/conte...
直接搜索会超时(附超时代码)
可以使用状态压缩 dp
解题思路
seat_map 用一个整数表示一行的状态
line_state 标识任意一行所有可行的座位安排(其实就是没有相邻的)因为单就一行来看,只要没人相邻就 ok
line_state 中任意一个和 seat_map 的任意一行做按位与,看是否变化,就可以知道这一行是否可以这么座(是否会坐到坏座位)
两行之间的是否合法,就是一行右移、左移再和另一行按位与。
本思路参考了排行榜上 leoGW 的代码,思路一致,但是重写了。
代码
class Solution:
def maxStudents(self, seats: List[List[str]]) -> int:
n = len(seats)
m = len(seats[0])
dp = [[-1] *(1<<m) for i in range(n)]
seat_map = [0] * n # 每个整数代表一行的座位,整数每个二进制位为 0 代表座位不能用, 1 代表能用
for i, l in enumerate(seats):
for ch in l:
if ch == ".":
seat_map[i] = (seat_map[i] << 1) + 1 # 1 代表当前座位可用
else:
seat_map[i] = (seat_map[i] << 1) + 0 # 0 代表当前座位不可用
line_state = []
num = []
for i in range(1<<m):
x = 3 # 3 的二进制是 011,表示有两个座位挨着的情况
f = True
for j in range(m):
if i & x == x: # 有相邻座位
f = False
break
x <<= 1
if not f: continue
line_state.append(i)
num.append(str(bin(i)).count('1'))
if i & seat_map[0] == i:
dp[0][i] = num[-1]
print(line_state)
print(num)
for i in range(1, n):
for j, jn in zip(line_state, num):
if j & seat_map[i] == j:
for k in line_state:
if ((j << 1) & k ==0 ) and ((j >> 1) & k == 0): # 两行没有斜对角的人
dp[i][j] = max(dp[i-1][k] + jn, dp[i][j])
return max(dp[n-1])
欢迎来我的博客: https://codeplot.top/
我的博客刷题分类:https://codeplot.top/categories/%E5%88%B7%E9%A2%98/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。