记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
5/25 1871. 跳跃游戏 VII
使用dpi表示到达位置i是否可行
dp0=true
判断i-maxJump~i-minJump之间的位置是否可行
可以维护一个前缀和 判断i-maxJump~i-minJump之间的位置是否可行
prefix_sumi = prefix_sumi-1 + (1 if dpi else 0)
如果prefix_sumi-maxJump - prefix_sumi-minJump-1 > 0 则dpi=true
如果可行则dpi=true
最后返回dpn-1
python
def canReach(s, minJump, maxJump):
"""
:type s: str
:type minJump: int
:type maxJump: int
:rtype: bool
"""
n = len(s)
dp = [False] * n
dp[0] = True
prefix_sum = [0] * n
prefix_sum[0] = 1
for i in range(1, n):
if s[i] == '0':
left = max(0, i - maxJump)
right = i - minJump
if right >= 0:
reachable_count = prefix_sum[right] - (prefix_sum[left - 1] if left > 0 else 0)
if reachable_count > 0:
dp[i] = True
prefix_sum[i] = prefix_sum[i - 1] + (1 if dp[i] else 0)
return dp[-1]
5/26 3120. 统计特殊字母的数量 I
使用两位二进制mask记录是否出现过某个字母的大写和小写
使用26位的数组记录每个字母的mask
如果mask=3说明大小写都出现了
python
def numberOfSpecialChars(word):
"""
:type word: str
:rtype: int
"""
mask = [0]*26
for c in word:
if c.isupper():
mask[ord(c)-ord('A')]|=(1<<1)
else:
mask[ord(c)-ord('a')]|=(1<<0)
ans = 0
for m in mask:
if m==3:
ans+=1
return ans
5/27 3121. 统计特殊字母的数量 II
使用两位二进制mask记录是否出现过某个字母的大写和小写
使用26位的数组记录每个字母的mask
如果mask=3说明大小写都出现了
tag为26为数组 记录是否符合每个小写都在第一个大写之前
从后往前遍历 到大写字母时 如果此时已经出现小写字母 那么说明该字母不符合
python
def numberOfSpecialChars(word):
"""
:type word: str
:rtype: int
"""
mask = [0]*26
tag = [True]*26
for c in list(word)[::-1]:
if c.isupper():
v = ord(c)-ord('A')
mask[v]|=(1<<1)
if mask[v]&1==1:
tag[v]=False
else:
mask[ord(c)-ord('a')]|=(1<<0)
ans = 0
for i,m in enumerate(mask):
if m==3 and tag[i]:
ans+=1
return ans
5/28 3093. 最长公共后缀查询
最长公共后缀,等价于把所有字符串反转后找最长公共前缀
把 wordsContainer 的每个单词反转后插入 Trie。
Trie 的每个节点维护一个 best_idx,表示经过该节点(即拥有该后缀)的候选单词中,
按规则最优的下标:
先选长度更短的单词
长度相同选下标更小
查询时,把 query 反转后在 Trie 中尽量往下走:
走到的最深节点对应最长匹配后缀
该节点的 best_idx 就是答案
若一开始就走不动,返回根节点 best_idx(即全局最短且下标最小)
python
def stringIndices(wordsContainer, wordsQuery):
"""
:type wordsContainer: List[str]
:type wordsQuery: List[str]
:rtype: List[int]
"""
class TrieNode(object):
__slots__ = ("children", "best_idx")
def __init__(self):
self.children = {}
self.best_idx = -1
def better(idx1, idx2):
"""返回两个下标中更优的那个(长度短优先,再下标小优先)。"""
if idx1 == -1:
return idx2
if idx2 == -1:
return idx1
len1 = len(wordsContainer[idx1])
len2 = len(wordsContainer[idx2])
if len1 != len2:
return idx1 if len1 < len2 else idx2
return idx1 if idx1 < idx2 else idx2
root = TrieNode()
# 建立反转 Trie,并在每个节点维护最优下标
for i, w in enumerate(wordsContainer):
root.best_idx = better(root.best_idx, i)
node = root
for ch in reversed(w):
if ch not in node.children:
node.children[ch] = TrieNode()
node = node.children[ch]
node.best_idx = better(node.best_idx, i)
ans = []
for q in wordsQuery:
node = root
best = root.best_idx
for ch in reversed(q):
if ch not in node.children:
break
node = node.children[ch]
best = node.best_idx
ans.append(best)
return ans
5/29 3300. 替换为数位和以后的最小元素
从前往后处理 记录最小值
python
def minElement(nums):
"""
:type nums: List[int]
:rtype: int
"""
def check(num):
ans=0
while num>0:
ans+=num%10
num//=10
return ans
n=len(nums)
min_val=float("inf")
for i in range(n):
min_val=min(min_val,check(nums[i]))
return min_val
5/30
python
5/31
python