算法训练营Day27

#Java #回溯 #Hard

开源学习资料

Feeling and experiences:

以下题目都比较困难,第一遍刷的时候,先看懂即可。

重新安排行程:力扣题目链接

给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。

所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。

  • 例如,行程 ["JFK", "LGA"]["JFK", "LGB"] 相比就更小,排序更靠前。

假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。

java 复制代码
class Solution {
    Map<String, PriorityQueue<String>> map = new HashMap<String, PriorityQueue<String>>();
    List<String> itinerary = new LinkedList<String>();

    public List<String> findItinerary(List<List<String>> tickets) {
        for (List<String> ticket : tickets) {
            String src = ticket.get(0), dst = ticket.get(1);
            if (!map.containsKey(src)) {
                map.put(src, new PriorityQueue<String>());
            }
            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"出发,覆盖所有航班至少一次的行程。

• 如果存在多种可能的行程,选择字典序最小的那一条。

  1. 关键概念:

• 涉及到类似于欧拉路径的概念,即通过图中的所有边恰好一次的路径。

  1. 数据结构选择:

• 使用哈希表(Map<String, PriorityQueue<String>> map)来存储从每个机场出发的航班。键是出发机场,值是一个优先级队列,包含按字典序排列的目的地机场。

• 使用链表(List<String> itinerary)来存储最终的行程。

  1. 算法流程:

• 构建图:遍历每张机票,构建出发地到目的地的映射,存入哈希表。

• 深度优先搜索(DFS):从"JFK"开始进行DFS,按字典序探索每个机场的所有目的地。

• 递归终止条件:当一个机场没有更多可飞往的目的地时,将其加入行程。

• 行程构建:由于DFS是先达到最深层再回溯,所以最终的行程是逆序的,需要反转链表得到正确顺序。

  1. 特殊情况处理:

• 当存在多条路径时,优先级队列确保按字典序选择路径。

• 由于题目中的图可能不是传统意义上的欧拉图(可能不包含所有边),算法的目标是覆盖所有给定的边。

N皇后:力扣题目链接

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q''.' 分别代表了皇后和空位。

java 复制代码
class Solution {
    public List<List<String>> solveNQueens(int n) {
        List<List<String>> solutions = new ArrayList<List<String>>();
        int[] queens = new int[n];
        Arrays.fill(queens, -1);
        Set<Integer> columns = new HashSet<Integer>();
        Set<Integer> diagonals1 = new HashSet<Integer>();
        Set<Integer> diagonals2 = new HashSet<Integer>();
        backtrack(solutions, queens, n, 0, columns, diagonals1, diagonals2);
        return solutions;
    }

    public void backtrack(List<List<String>> solutions, int[] queens, int n, int row, Set<Integer> columns, Set<Integer> diagonals1, Set<Integer> diagonals2) {
        if (row == n) {
            List<String> 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<String> generateBoard(int[] queens, int n) {
        List<String> board = new ArrayList<String>();
        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个皇后,使得它们互不攻击。

  1. 关键数据结构:

• int[] queens:存储每一行皇后的列位置。

• Set<Integer> columns, diagonals1, diagonals2:分别记录已经放置皇后的列和两组斜线,以检测冲突。

  1. 算法流程:

• 初始化:创建解集solutions,初始化queens数组和三个用于检测冲突的集合。

• 回溯搜索 (backtrack 方法):

• 如果已经处理完所有行,生成棋盘并添加到解集中。

• 在当前行,遍历所有列:

• 检查当前列和两个斜线方向是否已经有皇后(冲突检测)。

• 如果无冲突,放置皇后并更新冲突检测集合。

• 递归处理下一行。

• 回溯:撤销当前行皇后的放置,恢复冲突检测集合,尝试下一个位置。

  1. 生成棋盘 (generateBoard 方法):

• 根据每行皇后的位置,生成代表棋盘的字符串列表。

以上代码均为力扣答案~

谁家今夜扁舟子?

何处相思明月楼?

Fighting!

相关推荐
Yan.love6 分钟前
开发场景中Java 集合的最佳选择
java·数据结构·链表
椰椰椰耶9 分钟前
【文档搜索引擎】搜索模块的完整实现
java·搜索引擎
大G哥9 分钟前
java提高正则处理效率
java·开发语言
智慧老师40 分钟前
Spring基础分析13-Spring Security框架
java·后端·spring
lxyzcm41 分钟前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
V+zmm101341 小时前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
Oneforlove_twoforjob2 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13142 小时前
常用的缓存技术都有哪些
java
AiFlutter2 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
J不A秃V头A3 小时前
IntelliJ IDEA中设置激活的profile
java·intellij-idea