[Leetcode Weekly Contest]182
链接:LeetCode
[Leetcode]1394. 找出数组中的幸运数
在整数数组中,如果一个整数的出现频次和它的数值大小相等,我们就称这个整数为「幸运数」。
给你一个整数数组 arr,请你从中找出并返回一个幸运数。
- 如果数组中存在多个幸运数,只需返回 最大 的那个。
- 如果数组中不含幸运数,则返回 -1 。
字典不解释。
import collections
class Solution:
def findLucky(self, arr: List[int]) -> int:
count = collections.Counter(arr)
res = -1
for key in set(arr):
if key == count[key]:
res = max(res,key)
return res
[Leetcode]1395. 统计作战单位数
每 3 个士兵可以组成一个作战单位,分组规则如下:
从队伍中选出下标分别为 i、j、k 的 3 名士兵,他们的评分分别为 \(rating[i]\)、\(rating[j]\)、\(rating[k]\)
作战单位需满足:\(rating[i] < rating[j] < rating[k]\)或者\(rating[i] > rating[j] > rating[k]\),其中$ 0 <= i < j < k < n$
请你返回按上述条件可以组建的作战单位数量。每个士兵都可以是多个作战单位的一部分。
一个通用的想法是,是以某个位置作为固定数,比较两侧满足升序或者降序的士兵的个数,相乘相加即可。在寻找两侧比其大/小的数,可以采用遍历或者线段树的方法。
class Solution:
def numTeams(self, rating: List[int]) -> int:
return self.getNum(rating)+self.getNum(rating[::-1])
# 左小右大
def getNum(self,nums):
left = [0 for i in range(len(nums))]
right = [0 for i in range(len(nums))]
for i in range(len(nums)):
for j in range(i):
if nums[j] < nums[i]:
left[i] += 1
for j in range(i+1,len(nums)):
if nums[j] > nums[i]:
right[i] += 1
res = 0
for i in range(len(nums)):
res += left[i] * right[i]
return res
[Leetcode]1396. 设计地铁系统
请你实现一个类 UndergroundSystem ,它支持以下 3 种方法:
1. checkIn(int id, string stationName, int t)
编号为 id 的乘客在 t 时刻进入地铁站 stationName 。
一个乘客在同一时间只能在一个地铁站进入或者离开。
2. checkOut(int id, string stationName, int t)
编号为 id 的乘客在 t 时刻离开地铁站 stationName 。
3. getAverageTime(string startStation, string endStation)
- 返回从地铁站 startStation 到地铁站 endStation 的平均花费时间。
- 平均时间计算的行程包括当前为止所有从 startStation 直接到达 endStation 的行程。
- 调用 getAverageTime 时,询问的路线至少包含一趟行程。
你可以假设所有对 checkIn 和 checkOut 的调用都是符合逻辑的。也就是说,如果一个顾客在 t1 时刻到达某个地铁站,那么他离开的时间 t2 一定满足 t2 > t1 。所有的事件都按时间顺序给出。
使用字典保存信息,在查询平均时间时,只需要查询两个车站,得到总时间,和总次数
class UndergroundSystem:
def __init__(self):
self.ids = {}
self.underground = {}
def checkIn(self, id: int, stationName: str, t: int) -> None:
self.ids[id] = [stationName,t]
def checkOut(self, id: int, stationName: str, t: int) -> None:
start_stationName,start_time = self.ids[id]
check_stationName = start_stationName+stationName
pay_time = t-start_time
if check_stationName not in self.underground:
self.underground[check_stationName] = [1,pay_time]
else:
self.underground[check_stationName][0] += 1
self.underground[check_stationName][1] += pay_time
def getAverageTime(self, startStation: str, endStation: str) -> float:
times,time = self.underground[startStation+endStation]
return time/times
# Your UndergroundSystem object will be instantiated and called as such:
# obj = UndergroundSystem()
# obj.checkIn(id,stationName,t)
# obj.checkOut(id,stationName,t)
# param_3 = obj.getAverageTime(startStation,endStation)
[Leetcode]1397. 找到所有好字符串
给你两个长度为 n 的字符串 s1 和 s2 ,以及一个字符串 evil 。请你返回 好字符串 的数目。
好字符串 的定义为:它的长度为 n ,字典序大于等于 s1 ,字典序小于等于 s2 ,且不包含 evil 为子字符串。
由于答案可能很大,请你返回答案对\(10^9 + 7\)取余的结果。
示例 1:
输入:n = 2, s1 = "aa", s2 = "da", evil = "b"
输出:51
解释:总共有 25 个以 'a' 开头的好字符串:"aa","ac","ad",...,"az"。还有 25 个以 'c' 开头的好字符串:"ca","cc","cd",...,"cz"。最后,还有一个以 'd' 开头的好字符串:"da"。
示例 2:
输入:n = 8, s1 = "leetcode", s2 = "leetgoes", evil = "leet"
输出:0
解释:所有字典序大于等于 s1 且小于等于 s2 的字符串都以 evil 字符串 "leet" 开头。所以没有好字符串。
示例 3:
输入:n = 2, s1 = "gx", s2 = "gz", evil = "x"
输出:2
这道题是本周的压轴题,也是我第一次接触这种题型,收获很大,采用的是数位 DP + KMP的方法。数位DP 问题往往都是这样的题型,给定一个闭区间\([l, r]\),让你求这个区间中满足某种条件的数的总数。数位DP实际上是DFS+记忆化搜索,关于数位DP的基础知识可以参考数位DP。
这道题的最大难点在于,我们要求计算有多少个字符串“不包含”某个子串,通过KMP算法是便于我们找出当前字符串与模式串的最大匹配位数,当出现下一位不匹配时,我们可以直接找出下一个需要匹配的字符位置,这里也就是next数组的作用了。
class Solution:
def findGoodStrings(self, n: int, s1: str, s2: str, evil: str) -> int:
MOD = 1000000007
if s1 > s2:
return 0
self.next_ = self.getNext(evil)
self.dp = [[-1 for j in range(len(evil))] for i in range(n)]
ans = self.dfs(s2,evil,0, 0, True) % MOD - self.dfs(s1,evil,0, 0, True) % MOD + MOD
if evil not in s1:
ans += 1
return ans % MOD
def getNext(self, p):
p += '*'
len_p = len(p)
next = [-1 for i in range(len_p)]
j,k = 0,-1
while j<len_p-1:
if p[j] == p[k] or k==-1:
j+=1
k+=1
next[j] = k
else:
k = next[k]
return next
def dfs(self,s,evil,x,match,flag):
n,m = len(s),len(evil)
if match >= m:
return 0
if x >= n:
return 1
if not flag and self.dp[x][match] != -1:
return self.dp[x][match];
lim = s[x] if flag else 'z'
ret = 0
for k in range(ord('a'),ord(lim)+1):
cur = chr(k)
nxt = match;
while nxt > 0 and evil[nxt] != cur:
nxt = self.next_[nxt]
if cur == evil[nxt]: nxt += 1
ret += self.dfs(s,evil,x + 1, nxt, flag and (cur == lim))
if not flag: self.dp[x][match] = ret
return ret
参考:
leetcode