Given a 2D board containing 'X'
and 'O'
(the letter O), capture all regions surrounded by 'X'
.
A region is captured by flipping all 'O'
s into 'X'
s in that surrounded region.
X X X X X O O X X X O X X O X X
After running your function, the board should be:
X X X X X X X X X X X X X O X X
Explanation:
Surrounded regions shouldn’t be on the border, which means that any 'O'
on the border of the board are not flipped to 'X'
. Any 'O'
that is not on the border and it is not connected to an 'O'
on the border will be flipped to 'X'
. Two cells are connected if they are adjacent cells connected horizontally or vertically.
class Solution(object):
def solve(self, board):
"""
:type board: List[List[str]]
:rtype: void Do not return anything, modify board in-place instead.
"""
if not board:
return
self.row = len(board)
self.col = len(board[0])
for i in range(1,self.col-1):
if board[0][i] == 'O' and board[1][i] == 'O':
self.change(board,1,i)
if board[self.row-1][i] == 'O' and board[self.row-2][i] == 'O':
self.change(board,self.row-2,i)
for i in range(1,self.row-1):
if board[i][0] == 'O' and board[i][1] == 'O':
self.change(board,i,1)
if board[i][self.col-1] == 'O' and board[i][self.col-2] == 'O':
self.change(board,i,self.col-2)
for i in range(1,self.row-1):
for j in range(1,self.col-1):
if board[i][j] == 'O':
board[i][j] = 'X'
elif board[i][j] == 'W':
board[i][j] = 'O'
def change(self,board,i,j):
board[i][j] = 'W'
if j + 1 < self.col-1 and board[i][j+1] == 'O':
self.change(board,i,j+1)
if i + 1 < self.row - 1 and board[i+1][j] == 'O':
self.change(board,i+1,j)
if i - 1 > 0 and board[i-1][j] == 'O':
self.change(board,i-1,j)
if j - 1 > 0 and board[i][j-1] == 'O':
self.change(board,i,j-1)
Code(others):
class Solution(object):
def solve(self, board):
"""
:type board: List[List[str]]
:rtype: void Do not return anything, modify board in-place instead.
"""
if not any(board):
return
n, m = len(board), len(board[0])
q = [ij for k in range(max(n,m)) for ij in ((0, k), (n-1, k), (k, 0), (k, m-1))]
while q:
i, j = q.pop()
if 0 <= i < n and 0 <= j < m and board[i][j] == 'O':
board[i][j] = 'W'
q += (i, j-1), (i, j+1), (i-1, j), (i+1, j)
board[:] = [['XO'[c == 'W'] for c in row] for row in board]
总结:
从外围向里扩散。
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]
_______3______ / \ ___5__ ___1__ / \ / \ 6 _2 0 8 / \ 7 4
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 Output: 3 Explanation: The LCA of of nodes5
and1
is3.
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
res = root
if not root:
return self.res
res = self.find(root,p,q)[1]
return res
def find(self,root,p,q):
if not root:
return (0,root)
a = self.find(root.left,p,q)
b = self.find(root.right,p,q)
n = a[0] + b[0]
if a[1]:
res = a[1]
else:
res = b[1]
if root == p or root == q:
n += 1
if n == 2:
res = root
n -= 1
return (n,res)
Code(others):
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
if not root:
return None
if root==p:
if self.searchnode(root.left,q) or self.searchnode(root.right,q):
return root
return None
if root == q:
if self.searchnode(root.left, p) or self.searchnode(root.right, p):
return root
return None
if self.searchnode(p,q):
return p
if self.searchnode(q,p):
return q
pinleft=self.searchnode(root.left,p)
pinright=not pinleft
qinleft=self.searchnode(root.left,q)
qinright=not qinleft
if pinleft:
if qinright:
return root
return self.lowestCommonAncestor(root.left,p,q)
if qinleft:
if pinright:
return root
return self.lowestCommonAncestor(root.left,p,q)
return self.lowestCommonAncestor(root.right,p,q)
def searchnode(self, root, p):
if not root:
return False
if root == p:
return True
return self.searchnode(root.left, p) or self.searchnode(root.right, p)
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
pathP, pathQ = self.findPath(root, p), self.findPath(root, q)
lenP, lenQ = len(pathP), len(pathQ)
ans, x = None, 0
while x < min(lenP, lenQ) and pathP[x] == pathQ[x]:
ans, x = pathP[x], x + 1
return ans
def findPath(self, root, target):
stack = []
lastVisit = None
while stack or root:
if root:
stack.append(root)
root = root.left
else:
peek = stack[-1]
if peek.right and lastVisit != peek.right:
root = peek.right
else:
if peek == target:
return stack
lastVisit = stack.pop()
root = None
return stack
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
if root in (None,q,p):
return root
if self.isParent(p,q):
return p
if self.isParent(q,p):
return q
while root:
if self.isParent(root.left,p) and self.isParent(root.left,q):
root=root.left
elif self.isParent(root.right,p) and self.isParent(root.right,q):
root=root.right
else:
return root
return root
def isParent(self,p,q):
if not p:
return False
if p==q:
return True
return self.isParent(p.left,q) or self.isParent(p.right,q)
总结:
Given a non-empty binary tree, find the maximum path sum.
For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root.
Input: [1,2,3] 1 / \ 2 3 Output: 6
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def maxPathSum(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
self.treePathLen = []
res = self.pathSum(root)
return max(self.treePathLen)
def pathSum(self,root):
if not root:
return -float('inf')
leftLen = self.pathSum(root.left)
rightLen = self.pathSum(root.right)
if leftLen == -float('inf') and rightLen == -float('inf'):
treeLen = root.val
elif leftLen == -float('inf'):
treeLen = root.val + rightLen
elif rightLen == -float('inf'):
treeLen = root.val + leftLen
else:
treeLen = root.val + leftLen + rightLen
maxTreeLen = max(treeLen,leftLen,rightLen,root.val,max(leftLen,rightLen) + root.val)
self.treePathLen.append(maxTreeLen)
return max(max(leftLen,rightLen) + root.val, root.val)
Code(others):
class Solution(object):
maxVal = 0
def maxPathSum(self, root):
"""
:type root: TreeNode
:rtype: int
"""
global maxVal
maxVal = root.val
def maxSum(r):
if(r == None):
return 0
curVal = r.val
lmaxSum = maxSum(r.left)
rmaxSum = maxSum(r.right)
if(lmaxSum > 0):
curVal += lmaxSum
if(rmaxSum > 0):
curVal += rmaxSum
global maxVal
if(curVal > maxVal):
maxVal = curVal
return max(r.val, r.val + lmaxSum, r.val + rmaxSum)
maxSum(root)
return maxVal
总结:
There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A is a directfriend of B, and B is a direct friend of C, then A is an indirect friend of C. And we defined a friend circle is a group of students who are direct or indirect friends.
Given a N*N matrix M representing the friend relationship between students in the class. If M[i][j] = 1, then the ith and jth students are direct friends with each other, otherwise not. And you have to output the total number of friend circles among all the students.
Input: [[1,1,0], [1,1,0], [0,0,1]] Output: 2 Explanation:The 0th and 1st students are direct friends, so they are in a friend circle. The 2nd student himself is in a friend circle. So return 2.
class Solution(object):
def findCircleNum(self, M):
"""
:type M: List[List[int]]
:rtype: int
"""
row = len(M)
count = 0
mark = [True for i in range(row)]
for i in range(row):
if mark[i]:
self.dfs(M,mark,i)
count += 1
return count
def dfs(self,M,mark,i):
mark[i] = False
for j in range(len(M[0])):
if mark[j] and M[i][j] == 1:
self.dfs(M,mark,j)
Code(others):
class Solution(object):
def findCircleNum(self, M):
"""
:type M: List[List[int]]
:rtype: int
"""
if M ==[] or len(M)==0 or len(M[0])!=len(M):
return 0
ans = 0
rest = list(range(len(M)))
while rest:
stack = [rest.pop(0)]
while stack:
cur = stack.pop()
for x in [x for x in rest if M[cur][x]]:
rest.remove(x)
stack.append(x)
ans += 1
return ans
总结:
There are a total of n courses you have to take, labeled from 0
to n-1
.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
Input: 2, [[1,0]] Output: true Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
inDegree = [0 for i in range(numCourses)]
dic = {}
for i in prerequisites:
inDegree[i[0]] += 1
if i[1] not in dic:
dic[i[1]] = [i[0]]
else:
dic[i[1]].append(i[0])
stack = []
n = 0
for i in range(numCourses):
if inDegree[i] == 0:
stack.append(i)
while stack:
cur = stack.pop(0)
n += 1
if cur in dic:
for i in dic[cur]:
inDegree[i] -= 1
if inDegree[i] == 0:
stack.append(i)
if n == numCourses:
return True
else:
return False
Code(others):
class Solution(object):
def canFinish(self, n, pres):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
from collections import deque
ind = [[] for _ in xrange(n)] # indegree
oud = [0] * n # outdegree
for p in pres:
oud[p[0]] += 1
ind[p[1]].append(p[0])
dq = deque()
for i in xrange(n):
if oud[i] == 0:
dq.append(i)
k = 0
while dq:
x = dq.popleft()
k += 1
for i in ind[x]:
oud[i] -= 1
if oud[i] == 0:
dq.append(i)
return k == n
class Solution:
def canFinish(self, numCourses, prerequisites):
graph = [[] for _ in range(numCourses)]
visit = [0 for _ in range(numCourses)]
for x, y in prerequisites:
graph[x].append(y) # 生成每门课的全部先修课程列表,角标为当前课,内容为先修课程列表
def dfs(i):
if visit[i] == -1:
return False
if visit[i] == 1:
return True
visit[i] = -1
for j in graph[i]: # 循环检查所有先修课程的所有先修课程,有没有指向后修课程的,即为-1的
if not dfs(j):
return False
visit[i] = 1
return True
for i in range(numCourses): # 遍历每一门课,检查先修课程以及先修课程的先修课程。。。有没有环
if not dfs(i):
return False
return True
总结:
There are a total of n courses you have to take, labeled from 0
to n-1
.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses.
There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.
Input: 2, [[1,0]] Output:[0,1]
Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course order is[0,1] .
class Solution(object):
def findOrder(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: List[int]
"""
visit = [0 for i in range(numCourses)]
graph = [[] for i in range(numCourses)]
res = []
for i in prerequisites:
graph[i[0]].append(i[1])
def dfs(i):
if visit[i] == -1:
return False
elif visit[i] == 1:
return True
visit[i] = -1
for j in graph[i]:
if not dfs(j):
return False
visit[i] = 1
res.append(i)
return True
for i in range(numCourses):
if not dfs(i):
return []
return res
Code(others):
class Solution(object):
def findOrder(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: List[int]
"""
graph = [[] for _ in xrange(numCourses)]
ins = [0 for _ in xrange(numCourses)]
for a in prerequisites:
graph[a[1]].append(a[0])
ins[a[0]] += 1
q = []
for i in xrange(numCourses):
if ins[i] == 0:
q.append(i)
res = []
while len(q) > 0:
t = q.pop(0)
res.append(t)
for a in graph[t]:
ins[a] -= 1
if ins[a] == 0:
q.append(a)
return res if len(res) == numCourses else []
class Solution(object):
def findOrder(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: List[int]
"""
graph = [[] for _ in range(numCourses)]
level = [0 for _ in range(numCourses)]
visit = [0 for _ in range(numCourses)]
for x, y in prerequisites:
graph[x].append(y) # 生成每门课的全部先修课程列表,角标为当前课,内容为先修课程列表
def dfs(i):
_max = level[i]
if visit[i] == -1:
return False, _max
if visit[i] == 1:
return True, _max
visit[i] = -1
for j in graph[i]: # 循环检查所有先修课程的所有先修课程,有没有指向后修课程的,即为-1的
flag, _level = dfs(j)
if not flag:
return False, _max
_max = max(_max, _level+1)
level[i] = _max
visit[i] = 1
return True, _max
for i in range(numCourses): # 遍历每一门课,检查先修课程以及先修课程的先修课程。。。有没有环
flag, _level = dfs(i)
if not flag:
return []
res = {}
for k, v in enumerate(level):
if v not in res:
res[v] = []
res[v].append(k)
ret = []
i = 0
while True:
if i in res:
ret += res[i]
i += 1
else:
break
return ret
总结:
You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i]
is the number of smaller elements to the right of nums[i]
.
Input: [5,2,6,1]
Output: [2,1,1,0]
Explanation:
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.
class Solution(object):
def countSmaller(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
if not nums:
return nums
n = len(nums)
counts = [0 for i in range(n)]
temp = [nums[n-1]]
for i in range(n-2,-1,-1):
left = 0
right = len(temp)
while left < right:
mid = (left + right) // 2
if temp[mid] < nums[i]:
left = mid + 1
else:
right = mid
counts[i] = left
temp.insert(left,nums[i])
return counts
Code(others):
class BinaryIndexedTree(object):
def __init__(self, n):
self.sums = [0] * (n + 1)
def update(self, i, val):
while i < len(self.sums):
self.sums[i] += 1
i += i & -i
def sum(self, i):
r = 0
while i > 0:
r += self.sums[i]
i -= i & -i
return r
class Solution(object):
def countSmaller(self, nums):
hashTable = {v: i for i, v in enumerate(sorted(set(nums)))}
tree, r = BinaryIndexedTree(len(hashTable)), []
for i in xrange(len(nums) - 1, -1, -1):
r.append(tree.sum(hashTable[nums[i]]))
tree.update(hashTable[nums[i]] + 1, 1)
return r[::-1]
class Solution:
def countSmaller(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
tmp = []
ans = []
for i in nums[::-1]:
x = bisect.bisect_left(tmp, i)
ans.append(x)
tmp.insert(x, i)
return ans[::-1]
总结:
Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
Note:
Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] Output: 5 Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", return its length 5.
import string
class Solution(object):
def ladderLength(self, beginWord, endWord, wordList):
"""
:type beginWord: str
:type endWord: str
:type wordList: List[str]
:rtype: int
"""
if endWord not in wordList:
return 0
queue = [beginWord]
n = len(beginWord)
wordDic = {}
for i in wordList:
if i not in wordDic:
wordDic[i] = 1
lowercase = [i for i in string.lowercase]
dic = {}
dic[beginWord] = 1
while queue:
cur = queue.pop(0)
for i in range(n):
for j in lowercase:
temp = cur
if temp[i] == j:
continue
else:
temp = temp[:i] + j + temp[i+1:]
if temp == endWord:
return dic[cur] + 1
if temp in wordDic and temp not in dic:
queue.append(temp)
dic[temp] = dic[cur] + 1
if endWord not in dic:
return 0
return dic[endWord]
Code(others):
class Solution(object):
def ladderLength(self, beginWord, endWord, wordList):
if endWord not in wordList:
return 0
wordList = set(wordList)
forward, backward, n, cnt = {beginWord}, {endWord}, len(beginWord), 2
dic = set(string.ascii_lowercase)
while len(forward) > 0 and len(backward) > 0:
if len(forward) > len(backward): # 加速
forward, backward = backward, forward
next = set()
for word in forward:
for i, char in enumerate(word):
first, second = word[:i], word[i + 1:]
for c in dic: # 遍历26个字母
candidate = first + c + second
if candidate in backward: # 如果找到了,返回结果,没有找到,则在wordList中继续寻找
return cnt
if candidate in wordList:
wordList.discard(candidate) # 从wordList中去掉单词
next.add(candidate) #加入下一轮的bfs中
forward = next
cnt += 1
return 0
总结:
Given an integer matrix, find the length of the longest increasing path.
From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed).
Input: nums =
[
[9,9,4],
[6,6,8],
[2,1,1]
]
Output: 4
Explanation: The longest increasing path is [1, 2, 6, 9]
.
class Solution(object):
def longestIncreasingPath(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: int
"""
maxPathLen = 0
if not matrix:
return maxPathLen
row = len(matrix)
col = len(matrix[0])
path = [(1,0),(-1,0),(0,1),(0,-1)]
maxPath = [[-1 for j in range(col)] for i in range(row)]
def increasingPath(matrix,i,j,pre):
n = 0
if i < 0 or i >= row or j < 0 or j >= col:
return n
if matrix[i][j] > pre:
if maxPath[i][j] >= 0:
return maxPath[i][j]
for temp in path:
n = max(n, increasingPath(matrix, i + temp[0], j + temp[1], matrix[i][j]) + 1)
maxPath[i][j] = max(maxPath[i][j],n)
return n
for i in range(row):
for j in range(col):
m = 0
for k in path:
m = max(m, increasingPath(matrix, i + k[0], j + k[1], matrix[i][j]) + 1)
maxPath[i][j] = max(maxPath[i][j],m)
maxPathLen = max(maxPathLen, m)
return maxPathLen
Code(others):
class Solution(object):
def longestIncreasingPath(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: int
"""
if not matrix or not matrix[0]:
return 0
m = len(matrix)
n = len(matrix[0])
memo = [[0] * n for i in range(m)]
def helper(i, j):
if not memo[i][j]:
ans = 0
num = matrix[i][j]
if i > 0 and matrix[i-1][j] > num:
ans = max(ans, helper(i-1, j))
if j > 0 and matrix[i][j-1] > num:
ans = max(ans, helper(i, j-1))
if i < m - 1 and matrix[i+1][j] > num:
ans = max(ans, helper(i+1, j))
if j < n - 1 and matrix[i][j+1] > num:
ans = max(ans, helper(i, j+1))
memo[i][j] = ans + 1
return memo[i][j]
ans = 0
for i in range(m):
for j in range(n):
ans = max(ans, helper(i, j))
return ans
总结: