记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
8/10 1510. 石子游戏 IV
双方轮流从 n 个石子中拿走平方数个,Alice 先手,不能行动者输。
用 dpi 表示还剩 i 个石子时,当前选手是否必胜。
转移:若存在某个平方数 x,使得 dpi-x 为败,则当前选手必胜。
最终返回 dpn。
python
def winnerSquareGame(n):
"""
:type n: int
:rtype: bool
"""
dp = [False] * (n + 1)
for i in range(1, n + 1):
k = 1
while k * k <= i:
if not dp[i - k * k]:
dp[i] = True
break
k += 1
return dp[n]
8/11 2996. 大于等于顺序前缀和的最小缺失整数
从头遍历 找到顺序前缀并记录和
顺序前缀结束后
判断和是否出现过 若出现+1
python
def missingInteger(nums):
"""
:type nums: List[int]
:rtype: int
"""
ans=nums[0]
for i in range(1,len(nums)):
if nums[i]-nums[i-1]==1:
ans+=nums[i]
else:
break
s=set(nums)
while ans in s:
ans+=1
return ans
8/12 2958. 最多 K 个重复元素的最长子数组
滑动窗口l,r cntnum记录 num出现的次数
r一直往右移动 将numsr加入cnt 如果cntnums\[r] > k 则将numsl从cnt中移除 并左移l
如果cntnums\[r] <= k 则更新max_length
python
def maxSubarrayLength(nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
from collections import defaultdict
left = 0
right = 0
max_length = 0
cnt = defaultdict(int)
while right < len(nums):
cnt[nums[right]] += 1
while cnt[nums[right]] > k:
cnt[nums[left]] -= 1
left += 1
max_length = max(max_length, right - left + 1)
right += 1
return max_length
8/13 2213. 由单个字符重复的最长子字符串
每次单点改字符后,要求整串中最长连续相同字符的长度。
用线段树维护每个区间的:左端连续长度 lmx、右端连续长度 rmx、区间内最长连续长度 mx。
合并左右子区间时,若左区间右端字符等于右区间左端字符,则可把左后缀和右前缀拼起来更新 mx;若左区间整段相同,lmx 还要加上右前缀;若右区间整段相同,rmx 还要加上左后缀。
每次修改叶子后自底向上 pushup,根节点的 mx 就是当前答案。
python
def longestRepeating(s, queryCharacters, queryIndices):
"""
:type s: str
:type queryCharacters: str
:type queryIndices: List[int]
:rtype: List[int]
"""
n = len(s)
chars = list(s)
lmx = [0] * (n * 4)
rmx = [0] * (n * 4)
mx = [0] * (n * 4)
left = [0] * (n * 4)
right = [0] * (n * 4)
def pushup(u):
ls, rs = u << 1, u << 1 | 1
a = right[ls] - left[ls] + 1
b = right[rs] - left[rs] + 1
lmx[u] = lmx[ls]
rmx[u] = rmx[rs]
mx[u] = mx[ls] if mx[ls] > mx[rs] else mx[rs]
if chars[right[ls] - 1] == chars[left[rs] - 1]:
if lmx[ls] == a:
lmx[u] += lmx[rs]
if rmx[rs] == b:
rmx[u] += rmx[ls]
cross = rmx[ls] + lmx[rs]
if cross > mx[u]:
mx[u] = cross
def build(u, l, r):
left[u] = l
right[u] = r
if l == r:
lmx[u] = rmx[u] = mx[u] = 1
return
mid = (l + r) >> 1
build(u << 1, l, mid)
build(u << 1 | 1, mid + 1, r)
pushup(u)
def modify(u, x, v):
if left[u] == right[u]:
chars[x - 1] = v
return
mid = (left[u] + right[u]) >> 1
if x <= mid:
modify(u << 1, x, v)
else:
modify(u << 1 | 1, x, v)
pushup(u)
build(1, 1, n)
ans = []
for x, v in zip(queryIndices, queryCharacters):
modify(1, x + 1, v)
ans.append(mx[1])
return ans
8/14 3090. 每个字符最多出现两次的最长子字符串
滑动窗口 cnt记录每个字符出现的次数
如果当前字符出现的次数大于2,则移动左指针,直到当前字符出现的次数小于等于2
python
def maximumLengthSubstring(s):
"""
:type s: str
:rtype: int
"""
l,r=0,0
res=0
cnt=defaultdict(int)
while r<len(s):
cnt[s[r]]+=1
while cnt[s[r]]>2:
cnt[s[l]]-=1
l+=1
res=max(res,r-l+1)
r+=1
return res
8/15
python
8/16
python