332 重新安排行程
给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。
所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。
例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前。
假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。
# 回溯+used
def backtracking(tickets,used,path,cur,result):
if len(path)==len(tickets)+1:
result.append(path[:]) # 因为剪枝,对应下面找到一个路径就返回,不能return path[:]
return True
for i,ticket in enumerate(tickets):
if ticket[0]==cur and used[i]==False:
used[i]=True
path.append(ticket[1])
state=backtracking(tickets,used,path,ticket[1],result)
path.pop()
used[i]=False
if state:
return True # 找到一个路径就行,不需要再搜索
def findItinerary(tickets:'List[List[str]]')->'List[str]':
tickets.sort() #字母小的排在前面
used=[False]*len(tickets)
path=['JFK']
result=[]
backtracking(tickets,used,path,'JKF',result):
return result[0]
# 回溯+字典
# 待搞懂
def findItinerary(tickets):
target=defaultdict(list)
for ticket in tickets:
target[ticket[0]].append(ticket[1])
for airport in target:
target[airport].sort()
path=['JFK']
backtracking(target,path,len(tickets))
return path
def backtracking(target,path,ticketNum):
if len(path)==ticketNum+1:
return True
airport=path[-1]
destinations=target[airport]
for i,dest in enumerate(destinations):
target[airport].pop(i)
path.append(dest)
if backtracking(target,path,ticketNum):
return True
target[airport].insert(i,dest)
path.pop()
return False
51 N皇后
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
def solveNQueens(n:int)->'List[List[str]]':
result=[]
chessboard=['.'*n for _ in range(n)] # 原本n*n -> 1*n
backtracking(n,0,chessboard,result)
return [[''.join(row)for row in solution]for solution in result]
def backtracking(n,row,chessboard,result):
if row==n:
result.append(chessboard[:])
return
for col in range(n):
if isValid(row,col,chessboard):
chessboard[row]=chessboard[row][:col]+'Q'+chessboard[row][col+1:]
backtracking(n,row+1,chessboard,result)
chessboard[row]=chessboard[row][:col]+'.'+chessboard[row][col+1:]
def isValid(row,col,chessboard):
# 是否同一列出现多个Q
for i in range(row):
if chessboard[i][col]=='Q':
return False
# 是否45度角出现多个Q
i,j=row-1,col-1
while i>=0 and j>=0:
if chessboard[i][j]=='Q':
return False
i-=1
j-=1
# 是否135度角出现多个Q
i,j=row-1,col+1
while i>=0 and j<len(chessboard):
if chessboard[i][j]=='Q':
return False
i-=1
j+=1
return True
37 解数独
编写一个程序,通过填充空格来解决数独问题。
数独的解法需 遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。
def backtracking(board)->bool:
for i in range(len(board)):#行
for j in range(len(board[0])):#列
if board[i][j]!='.':
continue
for k in range(1,10):
if isValid(i,j,k,board):
board[i][j]=str(k)
if backtracking(board):
return True
board[i][j]='.'
return False #1-9都不能成功填入,无解返回Fasle
return True
def isValid(row,col,val,board)->bool:
for i in range(9):
if board[row][i]==str(val):
return False
for j in range(9):
if board[j][col]==str(val):
return False
# 根据row、col判断在第几个子子宫格内
start_row=(row//3)*3
start_col=(col//3)*3
for i in range(start_row,start_row+3):
for j in range(start_col,start_col+3):
if board[i][j]==str(val):
return False
return True
def solveSudoku(board:'List[List[str]]')->None:
backtracking(board)