Leetcode Contest 32
第一题Shortest Unsorted Continuous Subarray
首先将数组排好序,然后看排好的数组与原来的数组之间的差异。
class Solution(object):
def findUnsortedSubarray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
sn = sorted(nums)
i = 0
while i < len(nums) and nums[i] == sn[i]:
i += 1
if i == len(nums):
return 0
j = len(nums) - 1
while j >= 0 and nums[j] == sn[j]:
j -= 1
return j-i+1
第二题Kill Process
图/树的遍历问题。DFS和BFS都行。首先建立一个父进程与子进程的一一对应,然后从kill出发,逐一访问它的子进程,并递归下去。我是用BFS实现的。
class Solution(object):
def killProcess(self, pid, ppid, kill):
"""
:type pid: List[int]
:type ppid: List[int]
:type kill: int
:rtype: List[int]
"""
mp = {}
for c, p in zip(pid, ppid):
if p not in mp:
mp[p] = []
mp[p].append(c)
visited = {kill}
ans = [kill]
p = 0
while p < len(ans):
for c in mp.get(ans[p], []):
if c not in visited:
visited.add(c)
ans.append(c)
p += 1
return ans
第三题Delete Operation for Two Strings
求两个字符串最长公共子字符串的简单变种。本题答案是原来两个字符串长度之和减去最长公共子字符串的长度。下面我们看看怎么用动态规划寻找两个字符串的最长公共子字符串的长度。
假设给定的两个字符串为s和t,长度分别为n和m,用f(i, j)表示s[i:]与t[j:]的最长公共子字符串的长度。那么我们有如下转移方程:
如果s[i]==t[j]
否则
边界条件是:如果i >= n或者j >= m,f(i, j) = 0.
因为之前讨论过DP分别用递归和迭代实现的差异,所以今天就打算用不怎么熟悉的迭代来实现。然后赤裸裸的4次WA打脸了。有三次WA都是因为边界条件没有处理好!
class Solution(object):
def minDistance(self, word1, word2):
"""
:type word1: str
:type word2: str
:rtype: int
"""
if not word1 or not word2:
return len(word1)+len(word2)
n = len(word1)
m = len(word2)
dp = [[0]*m for _ in xrange(n)]
if word1[n-1] == word2[m-1]:
dp[n-1][m-1] = 1
ml = dp[n-1][m-1]
for i in xrange(m-2, -1, -1):
if word1[n-1]==word2[i]:
dp[n-1][i] = 1
else:
dp[n-1][i] = dp[n-1][i+1]
ml = max(ml, dp[n-1][i])
for i in xrange(n-2, -1, -1):
if word1[i]==word2[m-1]:
dp[i][m-1] = 1
else:
dp[i][m-1] = dp[i+1][m-1]
ml = max(ml, dp[i][m-1])
for j in xrange(m-2, -1, -1):
for i in xrange(n-2, -1, -1):
if word1[i]==word2[j]:
dp[i][j] = 1+dp[i+1][j+1]
else:
dp[i][j] = max(dp[i][j+1], dp[i+1][j])
ml = max(ml, dp[i][j])
return n+m-2*ml
上面代码奇丑无比。完成比赛后认真想想,上述代码可以简化为:
class Solution(object):
def minDistance(self, word1, word2):
"""
:type word1: str
:type word2: str
:rtype: int
"""
n, m = len(word1), len(word2)
dp = [[0]*(m+1) for _ in xrange(n+1)]
ml = 0
for j in xrange(m-1, -1, -1):
for i in xrange(n-1, -1, -1):
if word1[i]==word2[j]:
dp[i][j] = 1+dp[i+1][j+1]
else:
dp[i][j] = max(dp[i][j+1], dp[i+1][j])
ml = max(ml, dp[i][j])
return n+m-2*ml
第四题Erect the Fence
经典算法了,就不解释了。这个算法我好早之前就练习过了,比赛的时候就直接拷贝过来改改就提交过了。不知道这样做算不算作弊呢 >_<
# Definition for a point.
# class Point(object):
# def __init__(self, a=0, b=0):
# self.x = a
# self.y = b
class ConvexHull(object):
def __init__(self, points):
self.pts = points
self.hull = []
def get(self):
if len(self.hull) > 0:
return self.hull
pts, hull = self.pts, self.hull
is_turn_right = self.is_turn_right
pts.sort(key=lambda p: (p.x, p.y))
def calc_hull(pts):
ret = []
for p in pts:
if len(ret) < 2:
ret.append(p)
continue
while len(ret) > 1 and not is_turn_right(ret, p):
ret.pop()
ret.append(p)
return ret
# calculate upper hull
upper = calc_hull(pts)
# calculate lower hull
lower = calc_hull(reversed(pts))
hull = upper + lower[1:-1]
return list(set(hull))
def is_turn_right(self, pts, r):
p, q = pts[-2], pts[-1]
u = (q.x - p.x, q.y - p.y)
v = (r.x - p.x, r.y - p.y)
return u[0] * v[1] - u[1] * v[0] <= 0
class Solution(object):
def outerTrees(self, points):
"""
:type points: List[Point]
:rtype: List[Point]
"""
ch = ConvexHull(points)
return ch.get()