代码随想录打卡第三十二天|● 332.重新安排行程 ● 51. N皇后 ● 37. 解数独

332.重新安排行程

题目链接332.重新安排行程
如果存在多种有效的行程,请你按字符自然排序返回最小的行程组合。例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前
所有的机场都用三个大写字母表示(机场代码)。
假定所有机票至少存在一种合理的行程。
所有的机票必须都用一次 且 只能用一次。
示例 1:
输入:[[“MUC”, “LHR”], [“JFK”, “MUC”], [“SFO”, “SJC”], [“LHR”, “SFO”]]
输出:[“JFK”, “MUC”, “LHR”, “SFO”, “SJC”]
示例 2:
输入:[[“JFK”,“SFO”],[“JFK”,“ATL”],[“SFO”,“ATL”],[“ATL”,“JFK”],[“ATL”,“SFO”]]
输出:[“JFK”,“ATL”,“JFK”,“SFO”,“ATL”,“SFO”]
解释:另一种有效的行程是 [“JFK”,“SFO”,“ATL”,“JFK”,“ATL”,“SFO”]。但是它自然排序更大更靠后。
题目难点:
1.一个行程中,如果航班处理不好容易变成一个圈,成为死循环
2.有多种解法,字母序靠前排在前面,让很多同学望而退步,如何该记录映射关系呢 ? 难点在于容器的选择与使用
3.使用回溯法(也可以说深搜) 的话,那么终止条件是什么呢?
4.搜索的过程中,如何遍历一个机场所对应的所有机场
代码如下:
//超时 需使用Map降低搜索时间

class Solution {
    private LinkedList<String> res;
    private LinkedList<String> path = new LinkedList<>();
    public List<String> findItinerary(List<List<String>> tickets) {
        //排序
        Collections.sort(tickets, (a, b) -> a.get(1).compareTo(b.get(1))); 
        //加入起点
        path.add("JFK");
        //标记该点是否到达过
        boolean[] used = new boolean[tickets.size()];
        backTracking((ArrayList) tickets, used);
        return res;
        //如何返回字典序最小的组合,排序后已经达到效果 字典序小的被先找到
    }
     public boolean backTracking(ArrayList<List<String>> tickets, boolean[] used) {
         //遇到的机场个数,如果达到了(航班数量+1),那么我们就找到了一个行程
        if (path.size() == tickets.size() + 1) {
            res = new LinkedList(path);
            return true;
        }
        for (int i = 0; i < tickets.size(); i++) {
            if (!used[i] && tickets.get(i).get(0).equals(path.getLast())) {
                path.add(tickets.get(i).get(1));
                used[i] = true;
                //回溯
                //为什么返回值是bool类型
                //因为并不需要遍历整棵树 其遇到一个结果就返回
                if (backTracking(tickets, used)) {
                    return true;
                }

                used[i] = false;
                path.removeLast();
            }
        }
        return false;

     }
}

超时 如何使用Map降低搜索时间

51.N皇后

题目链接N皇后
解题思路:是一个二维回溯 注意判断是否合法的逻辑

class Solution {
    private List<List<String>> res=new ArrayList<>();

    public List<List<String>> solveNQueens(int n) {
        if(n==1){
           
           res.add(new ArrayList<>(Arrays.asList("Q")));
           return res;
        }
        if(n==2||n==3){
            return res;
        }
        char[][] arr = new char[n][n];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                arr[i][j] = '.';
            }
        }
        backtracking( arr,n, 0);
        return res;
    }
    //index表示当前是第几个皇后
    void backtracking(char[][] arr,int n,int index){
        //收集结果 最后一行的有效性什么时候判断 当有3行的时候 index=2是判断第三行 判断之后 index=3
        if(n==index){
            res.add(Array2List(arr));
            return;
        }
        for(int i=0;i<n;i++){
            if(isVaild(index,i,arr,n)){
                arr[index][i] = 'Q';
                backtracking( arr,n, index+1);
                arr[index][i] = '.';
            }
        }
    }
    //新建二维数组
    public List Array2List(char[][] chessboard) {
        List<String> list = new ArrayList<>();

        for (char[] c : chessboard) {
            list.add(String.copyValueOf(c));
        }
        return list;
    }
    //判断当前位置是否有效
    boolean isVaild(int row, int col, char[][] arr, int n){
        for (int i = 0; i < row; i++) { // 这是一个剪枝
            if (arr[i][col] == 'Q') {
             return false;
            }
        }
        //斜角
        for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {
            if (arr[i][j] == 'Q') {
                return false;
            }
        }
        
        for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
        if (arr[i][j] == 'Q') {
            return false;
        }
        }
        return true;
    }
}

解数独

题目链接:37. 解数独

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没脑袋的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值