sc onsite 31-40

P31 给两个节点,判断两个人是不是6度之内的朋友并且返回中间有多少人,之前面经看到,没写,真是后悔啊。一开始给了用queue和set的bfs解法,他说空间复杂度太高了,后来说用dfs,他说空间还是高,毕竟要用set存访问过的节点,我实在想不出来了,要了提示,可是感觉提示也并不是那么明显,我说能不能从两个点分别开始搜?他说你觉得这对复杂度有优化吗?我就觉得这估计也没戏。折腾了半天,好像也就剩20多分钟了,他说你先写一个你的解法,有时间我们再优化。写了那个bfs的,写完他让给test case,我忘了a和b是同一个人以及a和b中间人数多于6个的情况了,他提醒了一下加上了一两句判断。写好之后他看了觉得应该没bug了,让我问问题了,我还在纠结优化,他说10min估计不够了,优化是optional的(估计是安慰我的),然后让我问问题了。白人小哥是搞discovery的,我提了一个使用不是很顺的情况,他也说有蛮多人有抱怨的。中国小哥还给我讲了一些隐藏功能,他说他们也在想办法弄用户手册之类的,不然真的蛮难上手的

import collections
class Solution(object):
    def friend6(self, relations, a, b):
        dic = collections.defaultdict(set)
        for s,e in relations:
            dic[s].add(e)
            dic[s].add(e)

        visited = set([a])
        q = [(a, 0, [])]

        while q:
            p, d, path = q.pop(0)
            if d>6: return
            if p==b: return path+[p]
            for c in dic[p]:
                if c not in visited:
                    visited.add(c)
                    q.append((c, d+1, path+[p]))

        return

relations = [[1,2], [2,3], [3,4],[4,5]]
so = Solution()
ans = so.friend6(relations, 1, 5)
print ans

不知道优化空间是不是这个意思。

import collections
class Solution(object):
    def friend6(self, relations, a, b):
        dic = collections.defaultdict(set)
        for s,e in relations:
            dic[s].add(e)
            dic[s].add(e)

        visited = set([a])
        q = [(a, 0)]
        indegree = {}

        while q:
            p, d = q.pop(0)
            if d>6: return
            if p==b: break
            for c in dic[p]:
                if c not in visited:
                    visited.add(c)
                    indegree[c] = p
                    q.append((c, d+1))
        path = []
        while b!=a:
            path = [b] + path
            b = indegree[b]
        if b==a:
            path = [a] + path
        return path



relations = [[1,2], [2,3], [3,4],[4,5]]
so = Solution()
ans = so.friend6(relations, 1, 5)
print ans

P32 第四轮是个国人姐姐。问了问project,她好像也做过类似的,所以稍微多问了一点点。题目挺简单的,merge two sorted list, follow up是merge k sorted list,写完test case跑过了,问了问复杂度。她看还有好久再写一个吧,给inorder和postorder建树,我用recursion做,结果最后在子数组边界的地方加一减一的地方老是有问题,然后让她说没事,我相信你很快就能调好的,思路是对的,不用纠结了。

class Solution(object):
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        dummy = ListNode(None)
        head = dummy

        while l1 and l2:
          if l1.val<l2.val:
            dummy.next = l1
            dummy = dummy.next
            l1 = l1.next
          else:
            dummy.next = l2
            dummy = dummy.next
            l2 = l2.next

        dummy.next = l1 or l2

        return head.next

已经不知道写过多少遍了。

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, node = heapq.heappop(q)
            dummy.next = node
            dummy = dummy.next
            if dummy.next:
                heapq.heappush(q, (dummy.next.val, dummy.next))

        return head.next

P33 给一个nn的chess board,knight可以跳2\3的格子的对角线,就是国际象棋的规则。求给出一个起始点,knight能否跳到给定的重点。BFS搞定。followup print出来路径,backtrace就可以了,把每个格子上个格子的方位存下来,允许使用额外空间。写完后跑了test,小哥说:you did a good job

没太懂瞎写了一个。

class Solution(object):
    def knightMove(self, n, start):

        board = [[False]*n for _ in range(n)]

        q = [(start,[start])]

        while q:
            cur = q.pop(0)
            tmp, path = cur[0], cur[1]

            for dp in [(1,2), (-1,2), (1,-2), (-1,-2), (2,1), (2,-1), (-2,1),(-2,-1)]:
                i, j = tmp[0]+dp[0], tmp[1]+dp[1]
                if (i,j) == start: return path+[(i,j)]
                if 0<=i<n and 0<=j<n and not board[i][j]:
                    board[i][j] = True
                    q.append(((i,j), path+[(i,j)]))

so = Solution()
ans = so.knightMove(4, (0,0))

print ans

P34 给一个数组,A,B轮流从头尾处选出一个数字,求当B使用(1)贪心和(2)最优策略时,A能取到所有数字之和最大。我使用的recursive写的,优化用的是hash 存储从子数组(i, j)上能得到的最优解。写了几个test跑过了。

这道题跟我收录的dp的里面很像

B使用贪心的时候 A的解法。

class Solution(object):
    def maxCoin(self, nums):

        self.memo = {}
        res = self.helper(0, len(nums)-1, nums)
        print self.memo
        return res

    def helper(self, i, j, nums):

        if j-i<2:
            return max(nums[i:j+1])

        if (i, j) not in self.memo:
            l = nums[i]
            if nums[i+1]>nums[j]:
                l += self.helper(i+2,j,nums)
            else:
                l += self.helper(i+1,j-1,nums)
            r = nums[j]
            if nums[i]>nums[j-1]:
                r += self.helper(i+1,j-1,nums)
            else:
                r += self.helper(i, j-2, nums)
            self.memo[(i,j)] = max(l,r)
        return self.memo[(i,j)]

nums = [1,2,5,3]
so = Solution()
ans = so.maxCoin(nums)
print ans

B使用最优的时候的A的解法。

class Solution(object):
    def maxCoin(self, nums):

        self.memo = {}
        res = self.helper(0, len(nums)-1, nums)
        print self.memo
        return res

    def helper(self, i, j, nums):

        if j-i<2:
            return max(nums[i:j+1])

        if (i, j) not in self.memo:
            p2 = min(self.helper(i+1,j,nums), self.helper(i,j-1, nums))
            self.memo[(i,j)] = sum(nums[i:j+1]) - p2
        return self.memo[(i,j)]

nums = [1,9,1,3]
so = Solution()
ans = so.maxCoin(nums)
print ans

P35 第二轮,韩国大叔,Leetcode的symmetric tree。这题我一开始上来用了最精简的方法,然后似乎大叔不太能follow,要我从最简单的BFS做一遍,然后又从DFS做一遍。现在回过头来总结,其实面试的时候不要一开始给出最优解,给出一个相对naive但是直观的解,然后逐步改进,这样可以向面试官展现你的thinking process,一上来就最优的,很多面试官都不是很喜欢的。

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        return self.helper(root.left, root.right)

    def helper(self, l, r):
        if not l and not r: return True
        if not l or not r: return False
        if l.val!=r.val: return False

        return self.helper(l.left, r.right) and self.helper(l.right, r.left)

老天爷啊,求面试给我一道这种题目吧!!一道就行!!

就到这里了吧。不写了。考到没做过的。就看命咯。

祝看到这里的同学都能有个好前程,

哎呀,还是再写一个word break吧,有点不放心。

先来一个暴力的哈

class Solution(object):
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: Set[str]
        :rtype: List[str]
        """
        if not s:
            return []

        res = []
        self.dfs(s, wordDict, '', res)
        return res

    def dfs(self, s, wordDict, path, res):
        if not s:
            res.append(path)

        for w in wordDict:
            if s[:len(w)] == w:
                self.dfs(s[len(w):], wordDict, path+(' ' if path else '')+w, res)

s = "catsanddog"
dict = ["cat", "cats", "and", "sand", "dog"]
so = Solution()
a = so.wordBreak(s, dict)
print a

然后在用memo优化

class Solution(object):
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: Set[str]
        :rtype: List[str]
        """
        if not s:
            return []

        self.memo = {}
        return self.dfs(0, len(s), s, wordDict)

    def dfs(self, i, j, s, wordDict):

        if (i,j) not in self.memo:
            path = []
            if s[i:j] in wordDict:
                path += [s[i:j]]

            for w in wordDict:
                if len(w)<=j-i and s[i:i+len(w)]==w:
                    res = self.dfs(i+len(w), j, s, wordDict)
                    path += [w+' '+p for p in res]
            self.memo[(i,j)] = path
        return self.memo[(i,j)]


s = "catsanddog"
dict = ["cat", "cats", "and", "sand", "dog"]
so = Solution()
a = so.wordBreak(s, dict)
print a

酱油版的Dijkstra再写一遍吧。

class Solution(object):
    def dijkstra(self, graph, start, end):
        Q = {}
        P = {}
        D = {}

        Q[start] = 0

        while Q:
            k = self.findMin(Q)
            D[k] = Q[k]
            children = graph[k]
            for c in children:
                dis = D[k]+children[c]
                if c in D:
                    if dis<D[c]:
                        return
                elif c not in Q or dis<Q[c]:
                    Q[c] = dis
                    P[c] = k
            del Q[k]

        print P
        path, res = [], D[end]
        while end in P:
            path = [end] + path
            end = P[end]
        path = [end] + path

        return path,res

    def findMin(self, Q):
        m = (None, float('inf'))
        for k in Q:
            if Q[k]<m[1]:
                m = (k, Q[k])
        return m[0]


# example, CLR p.528
G = {'s': {'u':10, 'x':5},
    'u': {'v':1, 'x':2},
    'v': {'y':4},
    'x':{'u':3,'v':9,'y':2},
    'y':{'s':7,'v':6}}

so = Solution()
print so.dijkstra(G, 's', 'v')

再写个topo sort吧

import collections
class Solution(object):
    def toposort(self, graph):
        """
        :type graph: dict[int:List[int]]
        :rtype: List[int]
        """
        indegree = collections.defaultdict(set)
        outdegree = collections.defaultdict(set)
        for k in graph:
            for c in graph[k]:
                outdegree[k].add(c)
                indegree[c].add(k)



        s = [k for k in outdegree if k not in indegree]
        res = s[:]
        while s:
            tmp = s.pop()
            if tmp in outdegree:
                children = outdegree[tmp]
                for c in children:
                    indegree[c].remove(tmp)
                    if not indegree[c]:
                        s.append(c)
                        res.append(c)

        node = set(outdegree.keys()+indegree.keys())
        return res if len(res)==len(node) else []



graph = {1:[2,3,4,5],
        2:[3,4],
        3:[5]}
so = Solution()
a = so.toposort(graph)
print a
class Solution(object):
    def toposort(self, graph):
        """
        :type graph: dict[int:List[int]]
        :rtype: List[int]
        """
        children = []
        for k in graph:
            children += graph[k]
        s = [k for k in graph if k not in set(children)]

        res = []
        while s:
            while s[-1] in graph and graph[s[-1]]:
                c = graph[s[-1]].pop()
                if c in s:  # find circle
                    return []
                if c not in res:  # have visited node
                    s.append(c)
            res.append(s.pop())

        print res[::-1]

不管了,不管了。拿不到奥佛就算了!

results matching ""

    No results matching ""