这次周赛有点问题,第三题 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/


sxwxs
292 声望21 粉丝

计算机专业学生