#Java #回溯 #Hard
开源学习资料
Feeling and experiences:
以下题目都比较困难,第一遍刷的时候,先看懂即可。
给你一份航线列表 tickets
,其中 tickets[i] = [fromi, toi]
表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。
所有这些机票都属于一个从 JFK
(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK
开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。
["JFK", "LGA"]
与 ["JFK", "LGB"]
相比就更小,排序更靠前。假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。
class Solution {
Map> map = new HashMap>();
List itinerary = new LinkedList();
public List findItinerary(List> tickets) {
for (List ticket : tickets) {
String src = ticket.get(0), dst = ticket.get(1);
if (!map.containsKey(src)) {
map.put(src, new PriorityQueue());
}
map.get(src).offer(dst);
}
dfs("JFK");
Collections.reverse(itinerary);
return itinerary;
}
public void dfs(String curr) {
while (map.containsKey(curr) && map.get(curr).size() > 0) {
String tmp = map.get(curr).poll();
dfs(tmp);
}
itinerary.add(curr);
}
}
1. 问题理解:
• 目标是根据给定的航班列表,找到一条从”JFK”出发,覆盖所有航班至少一次的行程。
• 如果存在多种可能的行程,选择字典序最小的那一条。
2. 关键概念:
• 涉及到类似于欧拉路径的概念,即通过图中的所有边恰好一次的路径。
3. 数据结构选择:
• 使用哈希表(Map
• 使用链表(List
4. 算法流程:
• 构建图:遍历每张机票,构建出发地到目的地的映射,存入哈希表。
• 深度优先搜索(DFS):从”JFK”开始进行DFS,按字典序探索每个机场的所有目的地。
• 递归终止条件:当一个机场没有更多可飞往的目的地时,将其加入行程。
• 行程构建:由于DFS是先达到最深层再回溯,所以最终的行程是逆序的,需要反转链表得到正确顺序。
5. 特殊情况处理:
• 当存在多条路径时,优先级队列确保按字典序选择路径。
• 由于题目中的图可能不是传统意义上的欧拉图(可能不包含所有边),算法的目标是覆盖所有给定的边。
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
class Solution {
public List> solveNQueens(int n) {
List> solutions = new ArrayList>();
int[] queens = new int[n];
Arrays.fill(queens, -1);
Set columns = new HashSet();
Set diagonals1 = new HashSet();
Set diagonals2 = new HashSet();
backtrack(solutions, queens, n, 0, columns, diagonals1, diagonals2);
return solutions;
}
public void backtrack(List> solutions, int[] queens, int n, int row, Set columns, Set diagonals1, Set diagonals2) {
if (row == n) {
List board = generateBoard(queens, n);
solutions.add(board);
} else {
for (int i = 0; i < n; i++) {
if (columns.contains(i)) {
continue;
}
int diagonal1 = row - i;
if (diagonals1.contains(diagonal1)) {
continue;
}
int diagonal2 = row + i;
if (diagonals2.contains(diagonal2)) {
continue;
}
queens[row] = i;
columns.add(i);
diagonals1.add(diagonal1);
diagonals2.add(diagonal2);
backtrack(solutions, queens, n, row + 1, columns, diagonals1, diagonals2);
queens[row] = -1;
columns.remove(i);
diagonals1.remove(diagonal1);
diagonals2.remove(diagonal2);
}
}
}
public List generateBoard(int[] queens, int n) {
List board = new ArrayList();
for (int i = 0; i < n; i++) {
char[] row = new char[n];
Arrays.fill(row, '.');
row[queens[i]] = 'Q';
board.add(new String(row));
}
return board;
}
}
1. 问题定义:
• 在一个N×N的棋盘上放置N个皇后,使得它们互不攻击。
2. 关键数据结构:
• int[] queens:存储每一行皇后的列位置。
• Set
3. 算法流程:
• 初始化:创建解集solutions,初始化queens数组和三个用于检测冲突的集合。
• 回溯搜索 (backtrack 方法):
• 如果已经处理完所有行,生成棋盘并添加到解集中。
• 在当前行,遍历所有列:
• 检查当前列和两个斜线方向是否已经有皇后(冲突检测)。
• 如果无冲突,放置皇后并更新冲突检测集合。
• 递归处理下一行。
• 回溯:撤销当前行皇后的放置,恢复冲突检测集合,尝试下一个位置。
4. 生成棋盘 (generateBoard 方法):
• 根据每行皇后的位置,生成代表棋盘的字符串列表。
以上代码均为力扣答案~
谁家今夜扁舟子?
何处相思明月楼?
Fighting!