题目: 一个格子,填充0或者1.只能走0的位置。从左上角到右下角最短的路径长度。如果没有这样的路径,返回-1。 可以从8个方向走。
思路:
from collections import deque
class Solution:
def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:
m,n = len(grid), len(grid[0])
if grid[0][0] != 0:
return -1
# 第一个位置为0, 则加入到queue
queue = deque([[0,0]])
dir_x = [1,1,0,-1,-1,-1,0,1]
dir_y = [0,1,1,1,0,-1,-1,-1]
path_len = 1
grid[0][0] = 1 # 进栈代表走过, 走过的位置标记为1 不再走了
if 0==m-1==n-1:
return path_len
while queue:
length = len(queue)
for i in range(length):
x,y = queue.popleft()
for d in range(len(dir_x)):
x1, y1 = x+dir_x[d], y+dir_y[d]
if self.valid(x1, y1, m, n):
if grid[x1][y1] == 0: # 可以走到这里
if x1 == m-1 and y1 == n-1: # 走到终点
return path_len+1
else: # 如果不是终点
grid[x1][y1] = 1
queue.append([x1,y1])
path_len += 1
return -1
def valid(self, x, y, m,n):
if x<0 or y<0 or x>=m or y >=n:
return False
return True
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
main_diag = [0] * (2*n-1)
deputy_diag = [0] * (2*n-1)
queue = set()
ans = []
cols = [0] * n
rows = [0] * n
def can_place(row, col):
return not (cols[col] + main_diag[row-col] + deputy_diag[row+col])
def add_answer():
temp = []
for col in rows:
string = '.'*col + 'Q' + '.'*(n-1-col)
temp.append(string)
ans.append(temp)
def place(row, col):
cols[col] = 1
rows[row] = col
main_diag[row-col] = 1
deputy_diag[row+col] = 1
def cancel_place(row, col):
cols[col] = 0
rows[row] = 0
main_diag[row-col] = 0
deputy_diag[row+col] = 0
def backtrack(row):
if row == n:
add_answer()
return
for col in range(n):
if can_place(row, col):
place(row, col)
backtrack(row+1)
cancel_place(row, col)
backtrack(0)
return ans
class Solution:
def longestIncreasingPath(self, matrix: List[List[int]]) -> int:
dir = [[0,1],[0,-1],[1,0],[-1,0]]
def dfs(i,j):
nonlocal ans
if cache[i][j] != 0:
return cache[i][j]
for d in dir:
x, y = i+d[0], j+d[1]
if x <0 or x>=m or y<0 or y>=n or matrix[i][j] >= matrix[x][y]:
continue
cache[i][j] = max(cache[i][j], dfs(x,y))
cache[i][j] += 1
ans = max(ans, cache[i][j])
return cache[i][j]
if not matrix or not matrix[0]:
return 0
m,n = len(matrix), len(matrix[0])
ans = 0
cache =[[0]*n for _ in range(m)]
for i in range(m):
for j in range(n):
dfs(i,j)
return ans
class Solution:
def decodeString(self, s: str) -> str:
stack = []
n = len(s)
ans = ''
temp = ''
num = 0
for i in range(n):
if s[i].isdigit():
num = num*10 + int(s[i])
elif s[i] == '[':
stack.append((ans, num))
num = 0
ans = ''
elif s[i] == ']':
top = stack.pop()
ans = top[0] + ans * top[1]
else:
ans += s[i]
return ans
单词拆分|是求字典里面的单词能否组成一个string。||的要求是,把所有的组合罗列出来。动态规划和回溯递归都能做。但暴力法的递归是超时的。动态规划的dp[i]记录以i为结尾的串的所有合法组合,所以dp[i]是个list。
我写的是记忆化回溯
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
n = len(s)
rec = {}
def dfs(index):
if index in rec:
return rec[index]
res =[]
if index == n:
return [""]
for i in range(index, n):
sub = s[index:i+1]
if sub in wordDict:
temp = dfs(i+1)
for a in temp:
res.append(sub+' '+a if len(a)!=0 else sub)
rec[index] = res
return res
ans = dfs(0)
return ans
这道题的小坑是,不能用基本模板来写。我们想记录index到最后位置的子串能被字典单词组合的所有组合。这个是无法通过在结束条件那里保存的。我们需要逐个返回以i为起点的子串的所有合法组合。