记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
3/6 1653. 使字符串平衡的最少删除次数
左侧是a右侧是b
对于某一位置 可以删除右边的a+左边的b
从头遍历 对于每个位置判断 在当前满足条件的操作次数
def minimumDeletions(s):
"""
:type s: str
:rtype: int
"""
lb,ra = 0,s.count('a')
ans = ra
for c in s:
if c=='a':
ra -=1
else:
lb +=1
ans = min(ans,ra+lb)
return ans
3/7 1096. 花括号展开 II
递归解析
add用来生成两个set相加
如果遇到, 说明前后两部分相或
如果遇到{ 往后找到其对应的} 将这部分递归解析
如果前面为, 则将两部分相或 否则相加
其他符号则为表达式相连 根据前一个符号来决定相或 相加
def braceExpansionII(expression):
"""
:type expression: str
:rtype: List[str]
"""
def add(a,b):
ans = set()
for i in a:
for j in b:
ans.add(i+j)
return ans
def check(ex):
tmp = set()
ans = set()
loc = 0
last = ","
while loc<len(ex):
if ex[loc]==",":
ans = ans | tmp
tmp =set()
loc +=1
elif ex[loc]=="{":
cur = 1
x = loc+1
while cur>0:
if ex[x]=="{":
cur+=1
elif ex[x]=="}":
cur-=1
x+=1
if last ==",":
tmp = tmp | check(ex[loc+1:x-1])
else:
tmp = add(tmp,check(ex[loc+1:x-1]))
loc = x
last = "}"
else:
s = ""
while loc<len(ex) and ex[loc]!="," and ex[loc]!="{":
s += ex[loc]
loc+=1
if last==",":
tmp.add(s)
else:
tmp = {i+s for i in tmp}
last = ex[loc-1]
return ans | tmp
return sorted(check(expression))
3/8 剑指 Offer 47. 礼物的最大价值
每一格可由其左边或上边到达
从左上角开始 记录到达每个格子的最大价值
def maxValue(grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
m, n = len(grid), len(grid[0])
for j in range(1, n): # 初始化第一行
grid[0][j] += grid[0][j - 1]
for i in range(1, m): # 初始化第一列
grid[i][0] += grid[i - 1][0]
for i in range(1, m):
for j in range(1, n):
grid[i][j] += max(grid[i][j - 1], grid[i - 1][j])
return grid[-1][-1]
3/9 2379. 得到 K 个黑块的最少涂色次数
滑动窗口 长度为k
往右移动记录窗口内白色的数量
def minimumRecolors(blocks, k):
"""
:type blocks: str
:type k: int
:rtype: int
"""
wnum = 0
for i in range(k):
if blocks[i]=='W':
wnum +=1
ans = wnum
for i in range(k,len(blocks)):
if blocks[i]=='W':
wnum +=1
if blocks[i-k]=='W':
wnum -=1
print(i-k,i,wnum)
ans = min(ans,wnum)
return ans
3/10 1590. 使数组和能被 P 整除
value记录总和除以P的余数
mem[x]从头遍历记录余数x最近的位置
寻找当前位置为结尾能够取到value的最短长度
def minSubarray(nums, p):
"""
:type nums: List[int]
:type p: int
:rtype: int
"""
value = sum(nums)%p
if value==0:
return 0
mem = {}
mem[0]=-1
cur = 0
ans = len(nums)
for i,v in enumerate(nums):
cur = (cur+v)%p
if (cur-value)%p in mem:
ans = min(ans,i-mem[(cur-value)%p])
mem[cur] = i
if ans<len(nums):
return ans
return -1
3/11 面试题 17.05. 字母与数字
tag数组记录状态
遍历数组 遇到字母+1 遇到数字-1
如果当前位置tag=0 说明数组到这里字母与数字个数相同
endmap记录tag出现在数组中最靠后的位置
从后往前遍历tag数组
对于位置i为起点的满足条件的数组 及找到tag[i]最后出现的位置=endmap[tag[i]]
def findLongestSubarray(array):
"""
:type array: List[str]
:rtype: List[str]
"""
curr = 0
tag = [0]
for c in array:
if c.isdigit():
curr -=1
else:
curr +=1
tag.append(curr)
endmap = {}
maxlen = 0
ans = []
n = len(tag)
for i in range(n-1,-1,-1):
v = tag[i]
if v in endmap:
if maxlen<=(endmap[v]-i):
maxlen = endmap[v]-i
ans = array[i:endmap[v]]
else:
endmap[v] = i
return ans
3/12 1617. 统计子树中城市之间最大距离
节点数不大于15个 可以枚举所有子树
使用二进制来表示一个子树 1表示节点在子树内 0表示节点不在子树内
在一个子树中 使用BFS先找到子树一个端点
再从端点出发BFS求出子树两节点间的最大距离
def countSubgraphsForEachDiameter(n, edges):
"""
:type n: int
:type edges: List[List[int]]
:rtype: List[int]
"""
from collections import defaultdict
g = defaultdict(list)
for i,j in edges:
i-=1
j-=1
g[i].append(j)
g[j].append(i)
ans = [0]*(n-1)
global msk,nxt
nxt = 0
def bfs(node):
global msk,nxt
msk ^=1<<node
l = [node]
d = -1
while l:
tmp = []
d +=1
for v in l:
nxt = v
for nod in g[v]:
if msk>>nod &1:
msk ^= 1<<nod
tmp.append(nod)
l = tmp[:]
return d
for mask in range(1,1<<n):
if mask &(mask-1)==0:
continue
msk = mask
cur = msk.bit_length()-1
bfs(cur)
if msk == 0:
msk=mask
mx = bfs(nxt)
ans[mx-1]+=1
return ans