2013. Detect Squares
class DetectSquares:
def __init__(self):
self.c = Counter() # (x, y) 的个数
self.xy = collections.defaultdict(Counter)
def add(self, point: List[int]) -> None:
x, y = point
self.c[x, y] += 1
self.xy[x][y] += 1
def count(self, point: List[int]) -> int:
x, y = point
re = 0
for y2 in self.xy[x]:
if y2 == y:
continue # 要 positive area, 和当前重叠的不考虑
re += self.c[x, y2] * self.c[x + y2 - y, y] * self.c[x + y2 - y, y2]
re += self.c[x, y2] * self.c[x + y - y2, y] * self.c[x + y - y2, y2]
return re
588. Design In-Memory File System
在trie分类
362. Design Hit Counter
class HitCounter(object):
# hit: O(1). get_hit: O(300). This solution will scale perfectly!
def __init__(self):
self.count = [[i, 0] for i in xrange(1, 301)] # i是timestamp, 0是频率
def hit(self, timestamp):
idx = (timestamp - 1) % 300
if self.count[idx][0] == timestamp:
self.count[idx][1] += 1
else:
self.count[idx][0] = timestamp
self.count[idx][1] = 1
def getHits(self, timestamp):
res = 0
for time, c in self.count:
if timestamp - time < 300:
res += c
return res
348. Design Tic-Tac-Toe
class TicTacToe(object):
def __init__(self, n):
self.row, self.col = [0] * n, [0]*n
self.diag = self.anti_diag = 0
self.n = n
def move(self, row, col, player):
offset = 1 if player == 1 else -1
if row == col:
self.diag += offset
if row + col == self.n - 1:
self.anti_diag += offset
self.row[row] += offset
self.col[col] += offset
if self.n in (self.row[row], self.col[col], self.diag, self.anti_diag):
return 1
if -self.n in (self.row[row], self.col[col], self.diag, self.anti_diag):
return 2
return 0
794. Valid Tic-Tac-Toe State
情况1. X 的个数要比O 多一个 或者相等。
2.不能有X,O都赢的情况
3. X赢的话,X的个数一定是比O 多一个
4.O赢的话,O的个数一定是等于X的个数
class Solution(object):
def validTicTacToe(self, board):
r, c = [0]*3, [0]*3
dia, anti_dia = 0, 0
count = 0
for i in xrange(3):
for j in xrange(3):
offset = 0
if board[i][j] == 'X':
offset = 1
count += 1
elif board[i][j] == 'O':
offset = -1
count -= 1
r[i] += offset
c[j] += offset
if i == j:
dia += offset
if i + j == 2:
anti_dia += offset
if 3 in (r+c+[dia]+[anti_dia]) and (-3 in (r+c+[dia]+[anti_dia]) or count != 1):
return False
if count < 0 or count > 1:
return False
if -3 in (r+c+[dia]+[anti_dia]) and count != 0:
return False
return True
281. Zigzag Iterator
class ZigzagIterator(object):
def __init__(self, v1, v2):
self.q = [v for v in (v1, v2) if v]
def next(self):
temp = self.q.pop(0)
res = temp.pop(0)
if temp: self.q.append(temp)
return res
def hasNext(self):
if self.q:
return True
return False
146. LRU Cache
解法一:OrderedDict , 太好用了,但是太取巧了
class LRUCache(object):
def __init__(self, capacity):
"""
:type capacity: int
"""
self.dic = collections.OrderedDict()
self.remain = capacity
def get(self, key):
"""
:type key: int
:rtype: int
"""
if key not in self.dic:
return -1
v = self.dic.pop(key)
self.dic[key] = v
return v
def put(self, key, value):
"""
:type key: int
:type value: int
:rtype: void
"""
if key in self.dic:
self.dic.pop(key)
else:
if self.remain > 0:
self.remain -= 1
else:
self.dic.popitem(last=False)
self.dic[key] = value
方法二:链表结构,链表特点,如果节点没有被引用,则节点会被回收(删除)
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.pre = None
self.next = None
class LRUCache(object):
def __init__(self, capacity):
"""
:type capacity: int
"""
self.dic = {}
self.capacity = capacity
self.head = Node(0, 0)
self.tail = Node(0, 0)
self.head.next = self.tail
self.tail.pre = self.head
def get(self, key):
"""
:type key: int
:rtype: int
"""
if key in self.dic:
node = self.dic[key]
self._remove(node)
self._add(node)
return node.value
else:
return -1
def put(self, key, value):
"""
:type key: int
:type value: int
:rtype: void
"""
if key in self.dic:
self._remove(self.dic[key])
node = Node(key, value)
self._add(node)
self.dic[key] = node
if len(self.dic) > self.capacity:
n = self.head.next
self._remove(n)
del self.dic[n.key]
def _remove(self, node):
preNode = node.pre
nextNode = node.next
preNode.next = nextNode
nextNode.pre = preNode
def _add(self, node):
preNode = self.tail.pre
preNode.next = node
node.pre = preNode
node.next = self.tail
self.tail.pre = node
460. LFU Cache
class LFUCache(object):
def __init__(self, capacity):
self.remain = capacity
self.freqDic = collections.defaultdict(collections.OrderedDict) # freq: [key:value, ]
self.leastFreq = 1 # so that we can delete least frequent node
self.node = {} # node key: (value, freq)
def _update(self, key, value=None):
old_freq = self.node[key][1]
if not value:
value = self.node[key][0]
self.node[key] = (value, old_freq+1)
self.freqDic[old_freq].pop(key)
if len(self.freqDic[self.leastFreq]) == 0: # if the update node is the only one left with least frequence, then leastFreq+1
self.leastFreq += 1
self.freqDic[old_freq+1][key] = value
def get(self, key):
if key not in self.node:
return -1
self._update(key)
return self.node[key][0]
def put(self, key, value):
if key in self.node:
self._update(key, value)
else:
self.node[key] = (value, 1)
self.freqDic[1][key] = value # add before remove, so if the capacity is 0, you add then delete
if self.remain == 0:
removed_node = self.freqDic[self.leastFreq].popitem(last=False) # return: (key, value)
self.node.pop(removed_node[0])
else:
self.remain -= 1
self.leastFreq = 1
353. Design Snake Game
class SnakeGame(object):
def __init__(self, width, height, food):
"""
Initialize your data structure here.
@param width - screen width
@param height - screen height
@param food - A list of food positions
E.g food = [[1,1], [1,0]] means the first food is positioned at [1,1], the second is at [1,0].
:type width: int
:type height: int
:type food: List[List[int]]
"""
self.m = collections.defaultdict(dict) # 二维list会out of memory
self.food = food
if food:
x, y = self.food.pop(0)
self.m[x][y] = 'F'
self.m[0][0] = 'S'
self.row = height
self.col = width
self.head = (0, 0)
self.tail = [(0, 0)]
self.eat = 0
def move(self, d):
"""
Moves the snake.
@param direction - 'U' = Up, 'L' = Left, 'R' = Right, 'D' = Down
@return The game's score after the move. Return -1 if game over.
Game over when snake crosses the screen boundary or bites its body.
:type direction: str
:rtype: int
"""
def outBorder(x, y):
if 0 <= x < self.row and 0 <= y < self.col:
return False
return True
if d == 'U':
X, Y = -1, 0
elif d == 'D':
X, Y = 1, 0
elif d == 'L':
X, Y = 0, -1
elif d == 'R':
X, Y = 0, 1
x, y = self.head
X, Y = x+X, y+Y
# Game over
if outBorder(X, Y):
return -1
tx, ty = self.tail[0]
if (X, Y) != (tx, ty) and self.m[X].get(Y) == 'S': # 头部前进,尾巴就跟着缩走一格
return -1
# food
if self.m[X].get(Y) == 'F':
self.eat += 1
if self.food:
fx, fy = self.food.pop(0)
self.m[fx][fy] = 'F' # new food
else:
tail = self.tail.pop(0)
self.m[tail[0]][tail[1]] = 0 # remove tail
self.m[X][Y] = 'S'
self.head = X, Y # update head
self.tail.append([X, Y])
return self.eat