sc onsite 11-20
P11 Alien dict
具体参考 Topo Sort 其实可以试下另外一种写法的,有点懒,就算了哈。
import collections
class Solution(object):
def alienOrder(self, words):
"""
:type words: List[str]
:rtype: str
"""
# build graph
indegree = collections.defaultdict(set)
outdegree = collections.defaultdict(set)
for i in range(len(words)-1):
x, y = words[i], words[i+1]
index = 0
while index<min(len(x),len(y)) and x[index]==y[index]:
index +=1
if index<min(len(x),len(y)):
indegree[y[index]].add(x[index])
outdegree[x[index]].add(y[index])
s = [k for k in outdegree if k not in indegree]
res = []
while s:
tmp = s.pop()
res.append(tmp)
chidren = outdegree[tmp]
for c in chidren:
indegree[c].remove(tmp)
if not indegree[c]:
s.append(c)
chars = set(''.join(words))
if len(res) == len(chars):
return ''.join(res)
else:
return ''
words = [
"wrt",
"wrf",
"er",
"ett",
"rftt"
]
so = Solution()
so.alienOrder(words)
P12 ugly number 写一个臭数字全家福 哈哈哈
https://leetcode.com/problems/ugly-number/
class Solution(object):
def isUgly(self, num):
"""
:type num: int
:rtype: bool
"""
for p in 2,3,5:
while num!=0 and num%p==0:
num = num//p
return num==1
so = Solution()
a = so.isUgly(6)
print(a)
https://leetcode.com/problems/ugly-number-ii/
class Solution(object):
def nthUglyNumber(self, n):
"""
:type n: int
:rtype: int
"""
res = [1]
i2, i3, i5= 0, 0 ,0
while len(res)<n:
n2, n3, n5 = 2*res[i2], 3*res[i3], 5*res[i5]
val = min([n2, n3, n5])
if val==n2:
i2 += 1
if val==n3:
i3 += 1
if val==n5:
i5 += 1
res.append(val)
return res[-1]
n = 10
so = Solution()
ans = so.nthUglyNumber(n)
print(ans)
https://leetcode.com/problems/super-ugly-number/
import heapq
class Solution(object):
def nthSuperUglyNumber(self, n, primes):
"""
:type n: int
:type primes: List[int]
:rtype: int
"""
res = [1]
q = []
for p in primes:
heapq.heappush(q, (p, 0, p))
while len(res)<n:
val, i, p = q[0]
res.append(val)
while q and q[0][0]==val:
val, i, p = heapq.heappop(q)
heapq.heappush(q, (p*res[i+1], i+1, p))
return res[-1]
P13 merge k sorted list
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
import heapq
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
dummy = ListNode(None)
head = dummy
q = [(n.val ,n) for n in lists if n]
heapq.heapify(q)
while q:
val, n = heapq.heappop(q)
head.next = n
head = head.next
if n.next:
heapq.heappush(q, (n.next.val,n.next))
return dummy.next
好像这里用heapreplace要快一点。不过也没快多少。
import heapq
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
dummy = ListNode(None)
head = dummy
q = [(n.val ,n) for n in lists if n]
heapq.heapify(q)
while q:
val, n = q[0]
head.next = n
head = head.next
if not n.next:
heapq.heappop(q)
else:
heapq.heapreplace(q, (n.next.val, n.next))
return dummy.next
P14 8*8的棋盘 走K步从一个点走到另一个点有多少不同路径,之前在地里看到过但下面的都不对,先写了个dfs, 然后说简化,我说两头dfs, 然后说再简化,然后经他提示用dp做出来了, 思路是第K步走到一个格子一共有多少不同路径, 那么K+1步走到他周围八个点就是多少路径,解法类似Game of life开个buff数组
怎么越做他们家的题越觉得他们家的bar越低啊。什么菜题都拿出来考人。快把我招进去,我帮他们出两道酷酷的题目。我觉得这道题dp也没有简化复杂度。只是优化了空间。
class Solution(object):
def UniquePath(self, size, start, end, k):
res = []
self.dfs(start, end, [], k, size, res)
return res
def dfs(self, cur, end, path, k, size, res):
if not k:
if cur==end:
res.append(path)
return
for dp in [(1,0) ,(-1,0), (0,1), (0,-1)]:
i, j = cur[0]+dp[0], cur[1]+dp[1]
if 0<=i<size and 0<=j<size:
self.dfs((i,j), end, path+[(i,j)], k-1, size, res)
boardsize = 8
start = (0,0)
end = (3,3)
so = Solution()
ans = so.UniquePath(boardsize, start, end, 6)
print(ans)
P15 安排会议室 又是瞬间秒掉 https://leetcode.com/problems/meeting-rooms-ii/
class Solution(object):
def minMeetingRooms(self, intervals):
"""
:type intervals: List[List[int]]
:rtype: int
"""
times = []
for s, e in intervals:
times.append((s,1))
times.append((e,0))
times.sort()
rooms, avaliable = 0, 0
for t in times:
if t[1]:
if not avaliable:
rooms += 1
else:
avaliable -= 1
else:
avaliable += 1
return rooms
intervals = [[0, 30],[5, 10],[15, 20]]
so = Solution()
print so.minMeetingRooms(intervals)
我们加强一下这道题。除了计算房间的个数,还要给每个会议室分配房间号码。
class Solution(object):
def minMeetingRooms(self, intervals):
"""
:type intervals: List[List[int]]
:rtype: int
"""
times = []
room_num = {}
for s, e in intervals:
times.append((s,1,e))
times.append((e,0,s))
times.sort()
rooms, avaliable = 0, []
for t in times:
if t[1]:
if not avaliable: # make a new room num
rooms += 1
room_num[t[0]] = rooms
else: # use a empty room num
room_num[t[0]] = avaliable.pop(0)
else: # return a room
avaliable.append(room_num[t[2]])
return room_num
intervals = [[0, 30],[5, 10],[15, 20]]
so = Solution()
print so.minMeetingRooms(intervals)
P16 感觉是word search 简易版,一个字典,给个单词,判断单词在不在字典里。和第二轮一样,一下子就觉得应该用trie做,本来以为没啥问题,结果写search的时候脑抽了,写了个bug,改了一下,又跑了另一个test case,结果还有一个bug,还好及时改好了,估计这里减分了。follow up就是如果单词里有问号,代表任意字母,判断字典里是不是有这个pattern的单词。用dfs挺快写好了,跑了几个test case也没啥问题。他好像说挺好的,具体也没听清了,估计也是安慰安慰我。后来就聊了聊天,我问了问在这里和大公司的区别之类的。
那我们就先写一个简单的版本吧。
class Node(object):
def __init__(self):
self.dic = {}
self.isWord = False
class Solution(object):
def findWords(self, words, s):
root = Node()
# Build trie
for w in words:
tmp = root
for c in w:
if c not in tmp.dic:
tmp.dic[c] = Node()
tmp = tmp.dic[c]
tmp.isWord = True
ans = [i for i in root.dic]
print(ans)
tmp = root
for c in s:
if c not in tmp.dic:
return False
tmp = tmp.dic[c]
return tmp.isWord
words = ["oath","pea","eat","rain"]
s = "oath"
so = Solution()
ans = so.findWords(words, s)
print(ans)
然后我们再写一个带星号的。
class Node(object):
def __init__(self):
self.dic = {}
self.isWord = False
class Solution(object):
def findWords(self, words, s):
root = Node()
# Build trie
for w in words:
tmp = root
for c in w:
if c not in tmp.dic:
tmp.dic[c] = Node()
tmp = tmp.dic[c]
tmp.isWord = True
res = []
self.findAll(root, s, '', res)
return res
def findAll(self, node, s, path, res):
if not s:
if node.isWord==True:
res.append(path)
return
if s[0]=='*':
for n in node.dic:
self.findAll(node.dic[n], s[1:], path+n, res)
else:
if s[0] in node.dic:
self.findAll(node.dic[s[0]], s[1:], path+s[0], res)
words = ["oath","pea","eat","rain"]
s = "*a*h"
so = Solution()
ans = so.findWords(words, s)
print(ans)
P17 给inorder和postorder建树
class Solution(object):
def buildTree(self, inorder, postorder):
"""
:type inorder: List[int]
:type postorder: List[int]
:rtype: TreeNode
"""
if inorder:
num = postorder.pop()
root = TreeNode(num)
index = inorder.index(num)
root.right = self.buildTree(inorder[index+1:], postorder)
root.left = self.buildTree(inorder[:index], postorder)
return root
P18 lc Word Search II word search变形,输出字典里面每一个单词出现的次数。follow up是怎么scale,都要求把代码写下来然后运行 https://leetcode.com/problems/word-search-ii/
class Node(object):
def __init__(self):
self.dic = {}
self.isWord = False
class Solution(object):
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
root = Node()
for w in words:
cur = root
for c in w:
if c not in cur.dic:
cur.dic[c] = Node()
cur = cur.dic[c]
cur.isWord = True
res = []
for i in range(len(board)):
for j in range(len(board[0])):
self.bt(i, j, board, '', root, res)
return res
def bt(self, i, j, board, path, root, res):
if root.isWord:
res.append(path)
root.isWord = False
if 0<=i<len(board) and 0<=j<len(board[0]):
c = board[i][j]
if c in root.dic:
board[i][j]='#'
self.bt(i-1, j, board, path+c, root.dic[c], res)
self.bt(i+1, j, board, path+c, root.dic[c], res)
self.bt(i, j+1, board, path+c, root.dic[c], res)
self.bt(i, j-1, board, path+c, root.dic[c], res)
board[i][j]=c
P19
317 Shortest Distance from All Buildings
今天状态好,居然又写了一个更简单的版本,鼓掌!撒花!
class Solution(object):
def shortestDistance(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
if not grid or not grid[0]:
return -1
cost = [[0]*len(grid[0]) for _ in range(len(grid))]
cnt = 0 # count how many building we have visited
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j]==1:
self.bfs((i,j), grid, cost, cnt)
cnt -= 1
res = [cost[i][j] for i in range(len(grid)) for j in range(len(grid[0])) if grid[i][j]==cnt]
return min(res) if res else -1
def bfs(self, start, grid, cost, cnt):
q = [(start, 0)]
while q:
p, dist = q.pop(0)
for dp in [(1,0), (-1,0), (0,1), (0,-1)]:
i, j = p[0]+dp[0], p[1]+dp[1]
# only the position be visited by cnt times will append to queue
if 0<=i<len(grid) and 0<=j<len(grid[0]) and grid[i][j]==cnt:
cost[i][j] += dist+1
q.append(((i,j), dist+1))
grid[i][j] -= 1
296 Best Meeting Point 原来直接算meduim就行了?我觉得自己是个傻逼啊!
class Solution(object):
def minTotalDistance(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
if not grid or not grid[0]:
return
cost = [[0]*len(grid[0]) for _ in range(len(grid))]
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j]==1:
self.bfs((i,j), cost, grid)
res = [i for row in cost for i in row if i!=0]
return min(res) if res else -1
def bfs(self, start, cost, grid):
q = [(start, 0)]
visited = {start}
while q:
po, dist = q.pop(0)
for dp in [(1,0), (-1,0), (0,1), (0,-1)]:
i, j = po[0]+dp[0], po[1]+dp[1]
if 0<=i<len(grid) and 0<=j<len(grid[0])\
and (i,j) not in visited:
cost[i][j] += dist+1
q.append(((i, j),dist+1))
visited.add((i,j))
grid = [[1,0,0,0,1],[0,0,0,0,0],[0,0,1,0,0]]
so = Solution()
ans = so.minTotalDistance(grid)
print ans
大神的解法
class Solution(object):
def minTotalDistance(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
if not grid:
return 0
r, c = len(grid), len(grid[0])
sumr = [i for i in xrange(r) for j in xrange(c) if grid[i][j]]
sumc = [j for i in xrange(r) for j in xrange(c) if grid[i][j]]
sumr.sort()
sumc.sort()
mid_row = sumr[len(sumr)/2]
mid_col = sumc[len(sumc)/2]
return sum([abs(r-mid_row) for r in sumr]) + sum([abs(c-mid_col) for c in sumc])
P20 Big Integer加减,可正可负,听他描述完,有点想抽自己,看到有人说了类似题目的面经,但是说的是电面,就没准备,没想撞上了。题目大意: 传入一个String, 自己定定义BigInteger class的内部变量, 实现加减; 想了一下,本来想直接char arrar处理,发现把符号信息单独拿出来会简单很多, 所以就是BigInteger{int sign, int[] nums}, 然后就是实现, 两个数的符号 ++, --, +-, -+, 分情况写,没有全部写完,就写好了++, --, 小哥说没时间了,你写几个testcase 先跑一下这个吧,testcase 通过, done.
不带小数的加法和乘法。
class Solution(object):
def add(self, num1, num2):
"""
:type num1: str
:type num2: str
:rtype: str
"""
num1 = list(num1)[::-1]
num2 = list(num2)[::-1]
if len(num1)<len(num2):
num1, num2 = num2, num1
carry = 0
index = 0
while index<len(num1):
n2 = int(num2[index]) if index<len(num2) else 0
tmp = n2 + int(num1[index]) + carry
cur = tmp%10
carry = tmp//10
num1[index] = str(cur)
index += 1
if carry: num1.append('1')
return ''.join(num1[::-1])
def multiply(self, num1, num2):
"""
:type num1: str
:type num2: str
:rtype: str
"""
num1 = num1[::-1]
num2 = num2[::-1]
res = [0]*(len(num1) + len(num2))
for i in range(len(num2)):
for j in range(len(num1)):
tmp = int(num2[i])*int(num1[j])
res[j+i] += tmp
res[j+i+1] += res[j+i]//10
res[j+i] = res[j+i]%10
while len(res)>1 and res[-1]==0:
res.pop()
return ''.join(map(str,res))[::-1]
num1 = '124'
num2 = '5679'
so = Solution()
a = so.add(num1, num2)
print(a)
a = so.multiply(num1, num2)
print(a)