1)332.重新安排行程
332. 重新安排行程 - 力扣(LeetCode) (leetcode-cn.com)
弄了半天,还看了解释,好歹是弄完了,但是速度有些慢。
from collections import defaultdict
class Solution:
def findItinerary(self, tickets: list[list[str]]) -> list[str]:
ticketDict = defaultdict(list) #创建字典 key是开始 val是结束 然后剪枝
for start,ender in tickets:
ticketDict[start].append(ender)
def backtracking(instart):
if len(path)==len(tickets)+1:return #将其他递归跳出
ticketDict[instart].sort()
for i in ticketDict[instart]:
instartnext= ticketDict[instart].pop(0)
path.append(instartnext)
if len(path)==len(tickets)+1 and not res: return
if instartnext in ticketDict:backtracking(instartnext)
path.pop()
ticketDict[instart].append(instartnext)
res, path = [], ['JFK']
backtracking('JFK')
return res
好吧,用了别人的办法
class Solution:
def findItinerary(self, tickets: List[List[str]]) -> List[str]:
# defaultdic(list) 是为了方便直接append
tickets_dict = defaultdict(list)
for item in tickets:
tickets_dict[item[0]].append(item[1])
'''
tickets_dict里面的内容是这样的
{'JFK': ['SFO', 'ATL'], 'SFO': ['ATL'], 'ATL': ['JFK', 'SFO']})
'''
path = ["JFK"]
def backtracking(start_point):
# 终止条件
if len(path) == len(tickets) + 1: return True
tickets_dict[start_point].sort()
for _ in tickets_dict[start_point]:
#必须及时删除,避免出现死循环
end_point = tickets_dict[start_point].pop(0)
path.append(end_point)
# 只要找到一个就可以返回了
if backtracking(end_point): return True
path.pop()
tickets_dict[start_point].append(end_point)
backtracking("JFK")
return path
2)51.N皇后
51. N 皇后 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
def isVaild(path,row, col):
if 'Q' in path[row]: #横行
return True
for j in range(n): #竖行
if path[j][col]=='Q':
return True
for j in range(min(row,n-1-col)+1):
if path[row-j][col+j]=='Q': #斜向上
return True
for j in range(min(row,col)+1): #斜右向上
if path[row-j][col-j]=='Q':
return True
return False
def backstacking(path,index):
if index==n:return res.append([''.join(_) for _ in path])
for i in range(n):
if isVaild(path,index,i):continue #横竖斜存在Q则跳出这次循环
path[index][i]='Q'
backstacking(path,index+1)
path[index][i]='.'
path=[['.']*n for _ in range(n)] #创建n矩阵
res=[]
backstacking(path,0)
return res
3)解数独
37. 解数独 - 力扣(LeetCode) (leetcode-cn.com)
解数独的和第一题很像,不过第一题 有明显的结束标志,但是这道题没有,所以只能等他循环完成后面加个结束标志return True
if backtrakcing(board):return True 重点是这行,如果下一轮循环或者叫下一个位置点,没有找到,然后就执行下一行,把这次的点换回来,然后就进行下次 for val in range(1,10):
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
def is_valid(row, col, val):
# 判断同一行是否冲突
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
# 判断同一九宫格是否有冲突
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 backtrakcing(board):
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j]=='.':
for val in range(1,10):
if is_valid(i,j,val):
board[i][j]=str(val)
if backtrakcing(board):return True
board[i][j]='.'
# 若数字1-9都不能成功填入空格,返回False无解
return False #无解
return True # 有解 全部解完的
backtrakcing(board)
4)总结
这种复杂的,需要不断实验或者试填的都可以用以下这种形式
def backtrakcing(参数):
判断结束:return True
#可以通过(参数)驱动位置变化
#或者在for外层加循环体,以及判断来驱动位置变化
for 循环体:
填入数值
if backtrakcing(参数):return True #重要点
返回状态
return False