给你一份航线列表 tickets
,其中 tickets[i] = [fromi, toi]
表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。
所有这些机票都属于一个从 JFK
(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK
开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。
- 例如,行程
["JFK", "LGA"]
与["JFK", "LGB"]
相比就更小,排序更靠前。
假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次
思路:类似与DFS的回溯。航线列表的每一个元素就是图的两个点和它们连成的一个有向边,这道题目要做的就是寻找遍历所有点的路径,该路径的起点已经给出,并且需要满足最小行程组合。
为了保证是最小行程组合,可以先对列表进行排序,这样从头遍历时就是优先选择最小的行程。
既然要返回路径,那么就需要用回溯。需要明确:循环的起始点和终点,进入下一个递归的条件,回溯函数的参数。先看进入下一个递归的条件,每一次递归,都意味着到达了一个新的起点(旧的终点)那么我们需要找到该新起点对应的哪一条边,需要遍历整个列表直到找到新起点为止,由于一个列表可能有多个相同的起点,可以用used数组来标记这条边是否被使用过。
Python:
class Solution:
def findItinerary(self, tickets: List[List[str]]) -> List[str]:
ans = []
path = ["JFK"]
cur = "JFK"
used = [False for _ in range(len(tickets))]
tickets.sort()
self.backtracking(path, "JFK", used, tickets, ans)
return ans
def backtracking(self, path, cur, used,tickets,ans):
if len(path) == len(tickets) + 1:
ans.extend(path)
return True
for i, v in enumerate(tickets):
if v[0] == cur and not used[i]:
path.append(v[1])
used[i] = True
state = self.backtracking(path, v[1], used, tickets,ans)
used[i] = False
path.pop()
if state: # Stop seaching when have found a path
return True
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
思路:将搜索过程看成一棵树,棋盘的行就是树的深度,列就是树的宽度。在列的维度上遍历,当判断该位置可以放一个皇后时,就改变棋盘,然后进入下一行。关键是怎么判断可不可以放皇后。题目要求皇后彼此之间不能攻击,那么就需要判断该位置同列,四十五度角和135度角不能有皇后。
Python:
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
chessboard = ["." * n for _ in range(n)] # [[....],[....],[....],[....]]
ans = []
self.backtracking(n, chessboard, ans, 0)
return [[''.join(row) for row in solution] for solution in ans]
def backtracking(self, n, chessboard, ans, row):
if row == n:
ans.append(chessboard[:])
return
for col in range(n):
if self.isvalid(chessboard, row, col):
chessboard[row] = chessboard[row][:col] + 'Q' + chessboard[row][col+1:]
self.backtracking(n, chessboard, ans,row + 1)
chessboard[row] = chessboard[row][:col] + '.' + chessboard[row][col+1:]
def isvalid(self, chessboard, row, col):
for r in range(row):
if chessboard[r][col] == "Q":
return False
i, j = row - 1, col - 1
while i >= 0 and j >= 0:
if chessboard[i][j] == 'Q':
return False
i -= 1
j -= 1
i, j = row - 1, col + 1
while i >= 0 and j <= len(chessboard) - 1:
if chessboard[i][j] == "Q":
return False
i -= 1
j += 1
return True
编写一个程序,通过填充空格来解决数独问题。
数独的解法需 遵循如下规则:
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 '.'
表示。
Python: 死活过不了,很多细节没把握住(这个是参考答案)
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
self.backtracking(board)
def backtracking(self, board: List[List[str]]) -> bool:
# 若有解,返回True;若无解,返回False
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 self.is_valid(i, j, k, board):
board[i][j] = str(k)
if self.backtracking(board): return True
board[i][j] = '.'
# 若数字1-9都不能成功填入空格,返回False无解
return False
return True # 有解
def is_valid(self, row: int, col: int, val: int, board: List[List[str]]) -> 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
# 判断同一九宫格是否有冲突,
start_row = (row // 3) * 3 # 2 -> 0 -> 0 -> 0-2, 4 -> 1 -> 3 -> 3-5
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