[LeetCode周赛复盘] 第 115 场双周赛20231014
- 一、本周周赛总结
- 100095. 上一个遍历的整数
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 100078. 最长相邻不相等子序列 I
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 100077. 最长相邻不相等子序列 II
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 100029. 和带限制的子多重集合的数目
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 参考链接
一、本周周赛总结
- T1 模拟。
- T2 贪心。
- T3 DP类似LIS,构造路径方案。
- T4 分组前缀和优化的分组背包求方案数。
100095. 上一个遍历的整数
100095. 上一个遍历的整数
1. 题目描述
2. 思路分析
按题意模拟即可。
3. 代码实现
class Solution:
def lastVisitedIntegers(self, words: List[str]) -> List[int]:
ans = []
nums = []
k=0
for v in words:
if v[0].isdigit():
nums.append(int(v))
k = 0
else:
k += 1
if k > len(nums):
ans.append(-1)
else:
ans.append(nums[-k])
return ans
100078. 最长相邻不相等子序列 I
100078. 最长相邻不相等子序列 I
1. 题目描述
2. 思路分析
方法1
- 枚举第一个g是0还是1,然后贪心的向后取位置。
方法2
- 直接pairwise,相邻不同了,则可以取左边的,注意记得取最后一个。
3. 代码实现
class Solution:
def getWordsInLongestSubsequence(self, n: int, words: List[str], groups: List[int]) -> List[str]:
def f(s):
ans = [0,[]]
for w, g in zip(words,groups):
if g == s:
ans[0]+=1
ans[1].append(w)
s ^= 1
return ans
return max(f(0),f(1))[1]
100077. 最长相邻不相等子序列 II
100077. 最长相邻不相等子序列 II
1. 题目描述
2. 思路分析
- n方dp。
- 从前边满足的地方转移过来,注意记录一个from_index来储存路径。
3. 代码实现
def han(s, t):
return sum(x!=y for x,y in zip(s,t))
class Solution:
def getWordsInLongestSubsequence(self, n: int, words: List[str], groups: List[int]) -> List[str]:
f = [1]*n
from_index = [-1]*n
for i, (w, g) in enumerate(zip(words,groups)):
for j in range(i):
if g != groups[j] and len(w) == len(words[j]) and han(words[j], w) == 1 and f[j] >= f[i]:
f[i] = f[j] + 1
from_index[i] = j
i = f.index(max(f))
ans = []
while i != -1:
ans.append(words[i])
i = from_index[i]
return ans[::-1]
100029. 和带限制的子多重集合的数目
100029. 和带限制的子多重集合的数目
1. 题目描述
2. 思路分析
- 题目描述很复杂,但其实是分组背包求方案数。
- 这样的话,值域是2e4,物品数也是2e4。n方会TLE。
- 考虑优化,我们知道分组背包先遍历组,然后遍历体积,再遍历每组里的物品。
- 可以看到内层,f[j] += f[j-k]+…f[j-k*c],这里累计了1~c,并且间隔是一样的,考虑用前缀和优化。
- 可以用分组前缀和,类似滑窗。参考普通前缀和,我们向前边添加k个0,方便代码。
- 注意到,题目限制sum(nums)<=2e4,那么不同的数字最多有多少组呢?显然最小是1,2,3~,那么不同数字组最多是开方级别的。
- 因此复杂度变成了O(r√S)。
3. 代码实现
MOD = 10**9 + 7
class Solution:
def countSubMultisets(self, nums: List[int], l: int, r: int) -> int:
cnt = Counter(nums)
f = [cnt[0]+1] + [0] * r
s = 0
for k, c in cnt.items():
if k == 0:continue
s += k * c
pre = [0]*k
for v in f:
pre.append((v+pre[-k])%MOD)
for j in range(min(s, r), 0, -1):
# f[j] += f[j-k]+..f[j-k*c]
f[j] += pre[j] - pre[max(j-k*c, 0)]
f[j] %= MOD
return sum(f[l:]) %MOD