[LeetCode周赛复盘] 第 315 场周赛20221016
[LeetCode周赛复盘] 第 315 场周赛20221016
- 一、本周周赛总结
- 二、 [Easy] 6204. 与对应负数同时存在的最大正整数
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 三、[Medium] 6205. 反转之后不同整数的数目
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 四、[Medium] 6219. 反转之后的数字和
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 五、[Hard] 6207. 统计定界子数组的数目
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 六、参考链接
一、本周周赛总结
- 前三题很水,T4突然很难。
- T3没考虑0的情况wa一次。
- T4写了个九十多行单调栈,很难搞,wa一次。
- T1哈希表模拟
- T2哈希表模拟
- T3遍历模拟
- T4滑窗
二、 [Easy] 6204. 与对应负数同时存在的最大正整数
链接: 6204. 与对应负数同时存在的最大正整数
1. 题目描述
2. 思路分析
按题意模拟即可。
3. 代码实现
class Solution:
def findMaxK(self, nums: List[int]) -> int:
s = set(nums)
ans = -1
for v in nums:
if v > 0 and -v in s:
ans = max(ans,v)
return ans
三、[Medium] 6205. 反转之后不同整数的数目
链接: 6205. 反转之后不同整数的数目
1. 题目描述
2. 思路分析
按题意模拟即可。
- 由于是python 翻转时借用字符串更方便。
3. 代码实现
class Solution:
def countDistinctIntegers(self, nums: List[int]) -> int:
s = set(nums)
for v in nums:
x = int(str(v)[::-1])
s.add(x)
return len(s)
四、[Medium] 6219. 反转之后的数字和
链接: 6219. 反转之后的数字和
1. 题目描述
2. 思路分析
- 按题意模拟。
- 注意i的上界,如果不判断0,那么要取到num。
3. 代码实现
class Solution:
def sumOfNumberAndReverse(self, num: int) -> bool:
if num == 0:
return True
for i in range(num):
j = int(str(i)[::-1])
if i + j == num:
return True
return False
五、[Hard] 6207. 统计定界子数组的数目
链接: 6207. 统计定界子数组的数目
1. 题目描述
2. 思路分析
- 比赛时写了非常麻烦的单调栈(因为看到了区间最小最大)。
- 实际上滑窗是比较简单的思路:
- 数组中值不在[minK,maxK]区间内的数都是不能为答案做贡献的,这些点都用不了,因此这些点可以把数组分成很多段。
- 在这些段之间计算区间数量即可。
- 枚举区间右端点r,如何找左端点l的个数呢。
- 需要当前段内存在minK和maxK即可,l最左能取到段左端,最右能取到上一个min和max的左边那个。
- 这题也可以套板子二分,用线段树或者st都可以。
- 枚举每个下标作为r,它左边的最大值和最小值具有单调性。
3. 代码实现
class Solution:
def countSubarrays(self, nums: List[int], minK: int, maxK: int) -> int:
n = len(nums)
if minK == maxK:
ans = 0
f = [0]*n
if nums[0] == minK:
f[0] = 1
for i in range(1,n):
if nums[i] == minK:
f[i] = f[i-1]+1
return sum(f)
ans = 0
mn = -1
mx = -1
q = deque()
for r,v in enumerate(nums):
if v<minK or v > maxK:
mn = -1
mx = -1
q.clear()
continue
q.append(r)
if v == minK:
mn = r
if v == maxK:
mx = r
if mn >=0 and mx >= 0:
ans += min(mn,mx)-q[0] + 1
return ans
单调栈做法
class Solution:
def countSubarrays(self, nums: List[int], minK: int, maxK: int) -> int:
n = len(nums)
if minK == maxK:
ans = 0
f = [0]*n
if nums[0] == minK:
f[0] = 1
for i in range(1,n):
if nums[i] == minK:
f[i] = f[i-1]+1
return sum(f)
st = []
lmn = [-1]*n
lmx = [-1]*n
rmn = [n]*n
rmx = [n]*n
stmn = []
stmx = []
for i in range(n):
v = nums[i]
while stmn and nums[stmn[-1]] >= v:
stmn.pop()
if stmn:
lmn[i] = stmn[-1]
while stmx and nums[stmx[-1]] <= v:
stmx.pop()
if stmx:
lmx[i] = stmx[-1]
stmn.append(i)
stmx.append(i)
stmn = []
stmx = []
for i in range(n-1,-1,-1):
v = nums[i]
while stmn and nums[stmn[-1]] >= v:
stmn.pop()
if stmn:
rmn[i] = stmn[-1]
while stmx and nums[stmx[-1]] <= v:
stmx.pop()
if stmx:
rmx[i] = stmx[-1]
stmn.append(i)
stmx.append(i)
# print(list(zip(lmn,rmn)))
# print(list(zip(lmx,rmx) ) )
ans = 0
mn = []
mx = []
used = set()
lll = 0
for i in range(n):
if nums[i] == minK:
l,r = lmn[i]+1,rmn[i]-1
mn.append([i,l,r])
if mx : # 另一个
j,a,b = mx[-1]
if j not in used:
used.add(j)
if b>=l: # 交集
ll = max(a,l,lll)
lll = j+1
rr = min(b,r)
x,y = i,j
if x>y:
x,y = y,x
if ll<=i<=rr and ll<=j<=rr:
ans += (x-ll+1)*(rr-y+1)
# print(nums[i],maxK)
if nums[i] == maxK:
l,r = lmx[i]+1,rmx[i]-1
mx.append([i,l,r])
if mn:
j,a,b = mn[-1]
if j not in used:
used.add(j)
if b>=l:
ll = max(a,l,lll)
lll = j + 1
rr = min(b,r)
x,y = i,j
if x>y:
x,y = y,x
if ll<=i<=rr and ll<=j<=rr:
ans += (x-ll+1)*(rr-y+1)
# print(mn,mx)
return ans