LeetCode Contest 60
这次比赛不难,但是我在最简单的两题各错了一次。
第一题Flood Fill
我记得高中的时候学到Flood Fill这个词的时候有种莫名开心,可能是因为这个名字很形象地描述了DFS的过程吧。
class Solution(object):
def floodFill(self, image, sr, sc, newColor):
"""
:type image: List[List[int]]
:type sr: int
:type sc: int
:type newColor: int
:rtype: List[List[int]]
"""
visited = set()
n = len(image)
m = len(image[0])
color = image[sr][sc]
def dfs(r, c):
image[r][c] = newColor
visited.add((r, c))
for dr, dc in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
x, y = r+dr, c+dc
if x < 0 or y < 0 or x >= n or y >= m or image[x][y] != color:
continue
if (x, y) in visited:
continue
dfs(x, y)
dfs(sr, sc)
return image
第二题Sentence Similarity
首先建立一个哈希表建立词语间的相似关系,然后遍历两个句子中的每个词语进行判断即可。
class Solution(object):
def areSentencesSimilar(self, words1, words2, pairs):
"""
:type words1: List[str]
:type words2: List[str]
:type pairs: List[List[str]]
:rtype: bool
"""
if len(words1) != len(words2):
return False
m = {}
for a, b in pairs:
if a not in m:
m[a] = set([a])
m[a].add(b)
if b not in m:
m[b] = set([b])
m[b].add(a)
for a, b in zip(words1, words2):
if a not in m:
if a != b:
return False
else:
if b not in m[a]:
return False
return True
第三题Remove Comments
我们可以依次处理每个数,并以ans
表示当前消除后的数组。如果ans
是空的,或者这个数是正的,又或者ans
最后一个数是与当前的数都是负的(都往左运动),那么这个数不会跟ans
的数相遇,所以直接加进ans
即可。因此,产生碰撞时当前的数必然是负的。这意味着处理碰撞时只会涉及位于ans
最后位置的正数。详细算法参考如下代码。
class Solution(object):
def asteroidCollision(self, asteroids):
"""
:type asteroids: List[int]
:rtype: List[int]
"""
ans = []
for a in asteroids:
if not ans or a > 0 or ans[-1]*a > 0:
ans.append(a)
continue
while ans and ans[-1] > 0 and ans[-1]+a < 0:
ans.pop()
if not ans or ans[-1] < 0:
ans.append(a)
continue
if ans[-1]+a == 0:
ans.pop()
return ans
第四题Parse Lisp Expression
比较麻烦的题,我觉得难点在于局部变量以及全局变量的处理。我简单介绍一下下面代码中的三个关键函数:split
, get
和lisp
。
split
是将表达式ex
分成若干块,每一块都是合法的子表达式。
get
首先假设输入参数v
是一个变量,直接尝试转化成整数或者从局部变量集合ls
或者全局变量gs
中获得。如果上述方法无法获得v
的值,说明v
是一个表达式而不是变量,所以对v
调用lisp
函数。
lisp
的输入参数ex
表示一个表达式,gs
表示全局变量列表。首先调用split
函数将ex
分解,然后按照let
, add
和mult
分类讨论。
class Solution(object):
def evaluate(self, expression):
"""
:type expression: str
:rtype: int
"""
def split(ex):
el = []
cur = ''
p = 0
s = 5
if ex.startswith('(mult'):
s = 6
for ch in ex[s:-1]:
if ch == '(':
p += 1
elif ch == ')':
p -= 1
elif ch == ' ':
if p == 0:
el.append(cur)
cur = ''
continue
cur += ch
el.append(cur)
return el
def get(v, ls, gs):
try:
return int(v)
except:
if v in ls:
return ls[v]
for g in gs[::-1]:
if v in g:
return g[v]
gs.append(ls)
ans = lisp(v, gs)
gs.pop()
return ans
def lisp(ex, gs):
ls = {}
el = split(ex)
if ex.startswith('(let'):
for i in range(0, len(el)-1, 2):
ls[el[i]] = get(el[i+1], ls, gs)
return get(el[-1], ls, gs)
else:
first = get(el[0], ls, gs)
second = get(el[1], ls, gs)
if ex.startswith('(add'):
return first+second
else:
return first*second
return lisp(expression, [])