LC

P1. Word Pattern II

哎呀,第一道题就写得我死去活来的。

class Solution(object):
    def wordPatternMatch(self, pattern, str):
        """
        :type pattern: str
        :type str: str
        :rtype: bool
        """
        p2s = {}
        return self.dfs(pattern, str, p2s)

    def dfs(self, pattern, remain, p2s):
        if not pattern and not remain:
            return True

        if not pattern or not remain:
            return False

        for i in range(1, len(remain)+1):
            s = remain[:i]
            p = pattern[0]

            if p in p2s and p2s[p] == s:
                if self.dfs(pattern[1:], remain[i:], p2s):
                    return True
            elif p not in p2s and s not in p2s.values():
                p2s[p] = s
                if self.dfs(pattern[1:], remain[i:], p2s):
                    return True
                del p2s[p]
        return False

s = Solution()
ans = s.wordPatternMatch('abab', 'xyzabcxzyabc')
print ans

再用一种我觉得更好理解的写法吧。这道题的难点在于不要瞎back tracking。年少的时候不懂事,不知道每一个back tracking 背后都偷偷标好了价格。

class Solution(object):
    def wordPatternMatch(self, pattern, str):
        """
        :type pattern: str
        :type str: str
        :rtype: bool
        """
        return self.dfs(pattern, str, {}, {})

    def dfs(self, pattern, remain, p2s, s2p):
        #base case
        if not pattern and not remain:
            return True
        if not pattern or not remain:
            return False

        for i in range(1, len(remain)+1):
            s = remain[:i]
            p = pattern[0]

            # does not match then continue
            if p in p2s and p2s[p] != s:
                continue
            if s in s2p and s2p[s] != p:
                continue

            if p in p2s and p2s[p] == s: # already back tracked
                if self.dfs(pattern[1:], remain[i:], p2s, s2p):
                    return True
            else: # fresh back tracking.
                p2s[p] = s
                s2p[s] = p
                if self.dfs(pattern[1:], remain[i:], p2s, s2p):
                    return True
                del p2s[p]
                del s2p[s]
        return False

s = Solution()
ans = s.wordPatternMatch('abab', 'xyzabcxzyabc')
print ans

P2. Falling Squares

这道题倒是不难,就是把我翔都写出来了。先抄一个答案放这里。

class Solution:
    def fallingSquares(self, positions):
        """
        :type positions: List[List[int]]
        :rtype: List[int]
        """
        ans = []
        heights = {}
        for pos, side in positions:
            # finds nearby positions, if any
            left, right = pos, pos+side-1
            # compare to see if this block overlaps with L/R boundaries of existing blocks
            nearby = [key for key in heights.keys() if not (key[1] < pos or key[0] > right)]
            # finds height of block based on heights of existing and overlapping blocks
            if len(nearby) > 0:
                h = max(heights[key] for key in nearby) + side
            else:
                h = side
            # update the heights for left and right boundaries
            heights[(pos,right)] = h
            # add height to ans
            if len(ans) == 0:
                ans.append(h)
            else:
                ans.append(max(h,ans[-1]))
        return ans

s = Solution()
ans = s.fallingSquares([[1, 1], [2, 1]])
print ans

P3. Serialize and Deserialize Binary Tree

有段时间没写了。写出来的感觉很粗糙。勉强能用。看了下原来写的,觉得自己很屌啊!

class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Codec:

    def serialize(self, root):
        """Encodes a tree to a single string.

        :type root: TreeNode
        :rtype: str
        """
        return self.seriHelper(root, '')

    def seriHelper(self, root, res):
        if not root:
            return '#'

        l = self.seriHelper(root.left, res)
        r = self.seriHelper(root.right, res)
        return str(root.val) + ',' + l + ',' + r

    def deserialize(self, data):
        """Decodes your encoded data to tree.

        :type data: str
        :rtype: TreeNode
        """
        data = data.split(',')
        return self.deseriHelper(data)

    def deseriHelper(self, data):
        if data and data[0] == '#':
            data.pop(0)
            return None

        node = TreeNode(int(data.pop(0)))
        node.left = self.deseriHelper(data)
        node.right = self.deseriHelper(data)
        return node


a = TreeNode('1')
b = TreeNode('2')
c = TreeNode('3')
b.left, b.right = a, c

s = Codec()
ans = s.serialize(b)
print ans
ans = s.deserialize(ans)
print ans.val, ans.left.val, ans.right.val

P4. Sudoku Solver

好吧,这道题是典型的back tracking, 过了一年再来写。感觉又有一些感触。 主要是怎么back tracking。我发现我有时候还是有点处理不好recursive body。比如这道题。如果当前的位置不是'.', 那么就该直接return 他的下一位的结果。因为根本不用back tracking我记得之前好像也犯过类似的错误。

class Solution(object):
    def solveSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: void Do not return anything, modify board in-place instead.
        """
        if not board or not board[0]:
            return board

        dic = set()

        for i in range(len(board)):
            for j in range(len(board)):
                num = board[i][j]
                if num != '.':
                    row, col, square = ('row', i, num), ('col', j, num), (i//3, j//3, num)
                    dic.add(row)
                    dic.add(col)
                    dic.add(square)

        self.helper(0, 0, board, dic)
        return board

    def helper(self, i, j, board, dic):
        # print board[0], i, j
        if i == len(board)-1 and j == len(board[0]):
            return True

        if j == len(board[0]):
            i += 1
            j = 0

        if board[i][j] != '.':
            return self.helper(i, j+1, board, dic)

        for num in '123456789':
            row, col, square = ('row', i, num), ('col', j, num), (i//3, j//3, num)
            if row not in dic and col not in dic and square not in dic:
                board[i][j] = num
                dic.add(row)
                dic.add(col)
                dic.add(square)
                if self.helper(i, j+1, board, dic):
                    return True
                board[i][j] = '.'
                dic.remove(row)
                dic.remove(col)
                dic.remove(square)

board = [
[".",".","9","7","4","8",".",".","."],
["7",".",".",".",".",".",".",".","."],
[".","2",".","1",".","9",".",".","."],
[".",".","7",".",".",".","2","4","."],
[".","6","4",".","1",".","5","9","."],
[".","9","8",".",".",".","3",".","."],
[".",".",".","8",".","3",".","2","."],
[".",".",".",".",".",".",".",".","6"],
[".",".",".","2","7","5","9",".","."]]
s = Solution()
ans = s.solveSudoku(board)
print ans

另外一种号称更加清晰的方法

class Solution(object):
    def solveSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: void Do not return anything, modify board in-place instead.
        """
        self.board = board
        self.row = [[1]*10 for i in range(9)]
        self.col = [[1]*10 for i in range(9)]
        self.box = [[[1]*10 for i in range(3)] for _ in range(3)]

        for i in range(9):
            for j in range(9):
                if board[i][j]!='.':
                    v = int(board[i][j])
                    self.row[i][v] = self.col[j][v] = self.box[i//3][j//3][v] = 0
        self.BT(0, 0)


    def BT(self, i, j):
        if i==9:
            return True
        if self.board[i][j] != '.':
            return self.BT(i+ (j+1)//9, (j+1)%9)

        for v in range(1,10):
            if self.row[i][v] and self.col[j][v] and self.box[i//3][j//3][v]:
                self.board[i][j] = str(v)
                self.row[i][v] = self.col[j][v] = self.box[i//3][j//3][v] = 0
                if self.BT(i+ (j+1)//9, (j+1)%9): return True
                self.row[i][v] = self.col[j][v] = self.box[i//3][j//3][v] = 1
                self.board[i][j] = '.'
        return False
board = [
[".",".","9","7","4","8",".",".","."],
["7",".",".",".",".",".",".",".","."],
[".","2",".","1",".","9",".",".","."],
[".",".","7",".",".",".","2","4","."],
[".","6","4",".","1",".","5","9","."],
[".","9","8",".",".",".","3",".","."],
[".",".",".","8",".","3",".","2","."],
[".",".",".",".",".",".",".",".","6"],
[".",".",".","2","7","5","9",".","."]]
s = Solution()
ans = s.solveSudoku(board)
print board

P5. Word Break II

我好像在写word break 1的时候就把2给写了。

class Solution(object):
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: List[str]
        :rtype: List[str]
        """
        self.memo = collections.defaultdict(list)
        self.dfs(s, 0, len(s), wordDict)
        return self.memo[(0,len(s))]

    def dfs(self, s, i, j, wordDict):
        if (i, j) not in self.memo:
            if s[i:j] in wordDict:  # if in the dict add to memo
                self.memo[(i, j)] += [s[i:j]]
            for k in range(i+1,j):
                if s[i:k] in wordDict:  # take the first part
                    tail = self.dfs(s, k, j, wordDict)  # recurse rest
                    self.memo[(i,j)] += [s[i:k]+' '+t for t in tail]
        return self.memo[(i, j)]

P6. Merge k Sorted Lists

这道题我airbnb我刚写过呀。我直接复制粘贴过来一下好了。说明这道题真是高频题目

# 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
        """
        heap = []
        dummy = ListNode()
        cur = dummy

        for node in lists:
            if node:
                heapq.heappush(heap, [node.val, node])

        while heap:
            tmp = heapq.heappop(heap)
            cur.next = tmp
            cur = cur.next
            if tmp.next:
                heapq.heappush(heap, tmp.next)

        return dummy.next

P7. All O`one Data Structure

这道题说明了,平时瞎逼逼讨论数据结构确实有用。去年我跟玩神才讨论过这道题。你看这不就变成著名公司Uber的面试题目了么。来我们大概把这道题写一遍。这道题我也能AC, 说明我确实有点厉害啊。

class Node(object):

    def __init__(self, key):
        self.key = key
        self.count = 1
        self.left = None
        self.right = None

    def __repr__(self):
        print self.key
        return repr(self.right)


class AllOne(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.head = None
        self.tail = None
        self.dic = {}


    def inc(self, key):
        """
        Inserts a new key <Key> with value 1. Or increments an existing key by 1.
        :type key: str
        :rtype: void
        """
        if not self.dic:
            node = Node(key)
            self.dic[key] = node
            self.head = node
            self.tail = node
        else:
            if key not in self.dic:
                node = Node(key)
                self.dic[key] = node
                self.tail.right = node
                node.left = self.tail
                self.tail = node
            else:
                node = self.dic[key]
                node.count += 1
                while node.left and node.count > node.left.count:
                    # swap 2 nodes
                    if self.tail == node:
                        self.tail = node.left
                    self.swap(node.left, node)
                    if not node.left:
                        self.head = node


    def dec(self, key):
        """
        Decrements an existing key by 1. If Key's value is 1, remove it from the data structure.
        :type key: str
        :rtype: void
        """
        if key not in self.dic:
            return
        else:
            node  = self.dic[key]
            node.count -= 1
            while node.right and node.count < node.right.count:
                # swap 2 nodes
                if self.head == node:
                    self.head = node.right
                self.swap(node, node.right)
                if not node.right:
                    self.tail = node

            if not node.count and len(self.dic) == 1:
                self.head = None
                self.tail = None
                self.dic = {}

            if not node.count and node.left:
                self.tail = node.left
                del self.dic[key]
                node.left.right = None        


    def getMaxKey(self):
        """
        Returns one of the keys with maximal value.
        :rtype: str
        """
        if self.head:
            return self.head.key
        else:
            return ""


    def getMinKey(self):
        """
        Returns one of the keys with Minimal value.
        :rtype: str
        """
        if self.tail:
            return self.tail.key
        else:
            return ""

    def swap(self, left, right):
        leftLeft = left.left
        rightRirhgt = right.right

        left.right = rightRirhgt
        left.left = right
        right.left = leftLeft
        right.right = left
        if rightRirhgt:
            rightRirhgt.left = left
        if leftLeft:
            leftLeft.right = right


s = AllOne()
s.inc('a')
s.inc('b')
s.inc('c')
s.inc('d')
s.inc('a')
s.inc('b')
s.inc('c')
s.inc('d')
s.inc('c')
print s.tail.key
print s.tail.left.key
s.inc('d')
s.inc('d')
s.inc('a')

P8. Minimum Window Substring

果然Pokemon永远是高山啊!仰止仰止!抄一个答案以示尊敬。

def minWindow(self, s, t):
    need, missing = collections.Counter(t), len(t)
    i = I = J = 0
    for j, c in enumerate(s, 1):
        missing -= need[c] > 0
        need[c] -= 1
        if not missing:
            while i < j and need[s[i]] < 0:
                need[s[i]] += 1
                i += 1
            if not J or j - i <= J - I:
                I, J = i, j
    return s[I:J]

P9. Regular Expression Matching

面试前得记得再写一次哟

class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """

        dp = [ [False]*(len(s) + 1) for _ in range(len(p) + 1) ]
        dp[0][0] = True

        for i in range(1, len(p) + 1):
            for j in range(1, len(s) + 1):
                if p[i-1] == '.':
                    dp[i][j] = dp[i-1][j-1]
                elif p[i-1] == '*':
                    dp[i][j] = dp[i-1][j-1] or dp[i-1][j] or dp[i][j-1]
                    if i >= 2 and j >= 2:
                        dp[i][j-2] = dp[i-2][j-2]
                else:
                    dp[i][j] = dp[i-1][j-1] and p[i-1] == s[j-1]

        return dp[-1][-1] == 1

args = ["aab", "c*a*b"]
s = Solution()
print s.isMatch("aa","a")
print s.isMatch("aa","aa")
print s.isMatch("aaa","aa")
print s.isMatch("aa", "a*")
print s.isMatch("aa", ".*")
print s.isMatch("ab", ".*")
print s.isMatch("aab", "c*a*b")

P10. LRU Cache

hmm最后一题了。

import collections
class LRUCache(object):
    def __init__(self, capa):
        self.dic = collections.OrderedDict()
        self.capa = capa

    def get(self, key):
        if key in self.dic:
            value = self.dic.pop(key)
            self.dic[key] = value
            return value

    def set(self, key, val):
        if key in self.dic:
            self.dic.pop(key)
        elif len(self.dic)==self.capa:
            self.dic.popitem(last=False)
        self.dic[key]=val


so = LRUCache(5)
so.set(1,1)
so.set(2,2)
so.set(3,3)
so.set(4,4)
so.set(5,5)
so.set(6,6)
so.set(7,7)
print so.dic

results matching ""

    No results matching ""