332.重新安排行程
题目描述: 332.重新安排行程.
解法
回溯
class Solution(object):
def backtrack(self,path,start):
if len(path) == len(self.tickets)+1:
self.res = path[:]
return True
#self.res.append()
for i,ticket in enumerate(self.tickets):
if not self.used[i] and ticket[0] == start:
path.append(ticket[1])
self.used[i] = True
state = self.backtrack(path,ticket[1])
self.used[i] = False
path.pop()
if state:
return True
def findItinerary(self, tickets):
self.tickets = tickets
self.tickets.sort()
self.used = [False] * len(self.tickets)
self.res = None
self.backtrack(["JFK"],"JFK")
return self.res
本体相对来说比较简单,首先是可以限定出发点,也就是path的头确定了,然后只需要加入一个used数组,就知道这张票有没有用过了。
需要注意的点是,path长度应该是票数+1。
此外就是为了能保证输出的是最小路径,其实可以上来先进行排序,这样就能保证第一个遍历到的完整路径一定是最小路径。
还有一个需要注意的点是,为了能直接返回第一个遍历成功的路径,可以设定一个True返回值,然后在每次回溯结束之后进行判断,若是True就返回上一层。
51. N皇后
题目描述: 51. N皇后.
解法
回溯
class Solution(object):
def check(self,floor,i):
p = floor-1
q = i - 1
while p>=0 and q>=0:
if self.chessboard[p][q] == 'Q':
return False
p-=1
q-=1
p = floor - 1
q = i+1
while p>=0 and q < self.length:
if self.chessboard[p][q] == 'Q':
return False
p-=1
q+=1
return True
def backtrack(self,floor):
if floor == self.length:
self.res.append(self.chessboard[:])
return
for i in range(self.length):
if self.used[i] or not self.check(floor,i):
continue
self.used[i] = True
self.chessboard[floor] = self.chessboard[floor][:i] + 'Q' + self.chessboard[floor][i+1:]
self.backtrack(floor+1)
self.chessboard[floor] = self.chessboard[floor][:i] + '.' + self.chessboard[floor][i+1:]
self.used[i] = False
def solveNQueens(self, n):
self.length = n
self.chessboard = ['.' * n for _ in range(n)]
self.used = [False] * n
self.res = []
self.backtrack(0)
return self.res
整体思路并不难,主要的问题就在
1.如何设计棋盘
使用二维数组即可
2.如何判定上下还有倾斜的问题
在每一层回溯中,可以保证同一层不会出现重复,使用used数组可以保证一列不会出现重复。
倾斜的话就考虑当前的位置在哪,然后往左上和右上循环即可,因为当前点的下层还没插入,所以不需要考虑往左下和右下的问题
3.如何修改棋盘
由于是str类型,所以不能直接使用索引进行修改,只能是通过切片的方式。
37. 解数独
题目描述: 37. 解数独.
解法
回溯
class Solution(object):
def vaild(self,i,j,k,board):
for p in range(len(board)):
if board[p][j] == str(k):
return False
if board[i][p] == str(k):
return False
p_start = (i//3) * 3
q_start = (j//3) * 3
for p in range(p_start,p_start+3):
for q in range(q_start,q_start+3):
if board[p][q] == str(k):
return False
return True
def backtrack(self,board):
for i in range(9):
for j in range(9):
if board[i][j] != '.':
continue
for k in range(1,10):
if self.vaild(i,j,k,board):
board[i][j] = str(k)
if self.backtrack(board):
return True
board[i][j] = '.'
return False
return True
def solveSudoku(self, board):
self.backtrack(board)
思路就是在一个棋盘上的每一个点进行回溯,不要想象成一个二维的期盼,把它想象成一个长数组,需要我们去填空,然后每一个空都可能是1-9,每一个空进行一次回溯,如果到了最后一个空返回的是True,就一层一层向上,如果某个位置1-9都不合适,就可以从这个回溯中出去了,要回到上一层重新进行回溯。