代码随想录三刷day28

本文详细介绍了如何使用回溯法解决力扣编程题目,包括重新安排行程(332)、N皇后(51)以及解数独(37),涉及递归、去重策略以及二维逻辑的应用。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言


如何理解回溯法的搜索过程? 什么时候用startIndex,什么时候不用? 如何去重?如何理解“树枝去重”与“树层去重”? 去重的几种方法? 如何理解二维递归?

一、力扣332. 重新安排行程

class Solution {
    private Deque<String> res;
    private Map<String, Map<String, Integer>> map;

    private boolean backTracking(int ticketNum){
        if(res.size() == ticketNum + 1){
            return true;
        }
        String last = res.getLast();
        if(map.containsKey(last)){//防止出现null
            for(Map.Entry<String, Integer> target : map.get(last).entrySet()){
                int count = target.getValue();
                if(count > 0){
                    res.add(target.getKey());
                    target.setValue(count - 1);
                    if(backTracking(ticketNum)) return true;
                    res.removeLast();
                    target.setValue(count);
                }
            }
        }
        return false;
    }

    public List<String> findItinerary(List<List<String>> tickets) {
        map = new HashMap<String, Map<String, Integer>>();
        res = new LinkedList<>();
        for(List<String> t : tickets){
            Map<String, Integer> temp;
            if(map.containsKey(t.get(0))){
                temp = map.get(t.get(0));
                temp.put(t.get(1), temp.getOrDefault(t.get(1), 0) + 1);
            }else{
                temp = new TreeMap<>();//升序Map
                temp.put(t.get(1), 1);
            }
            map.put(t.get(0), temp);

        }
        res.add("JFK");
        backTracking(tickets.size());
        return new ArrayList<>(res);
    }
}

二、力扣51. N 皇后

在这里插入代码片class Solution {
    List<List<String>> res = new ArrayList<>();
    char[][] path;
    public List<List<String>> solveNQueens(int n) {
        path = new char[n][n];
        for(char[] c : path){
            Arrays.fill(c,'.');
        }
        fun(n,0);
        return res;
    }
    public void f(int n){
        List<String> p = new ArrayList<>();
        for(int i = 0; i < n; i ++){
            StringBuilder s = new StringBuilder();
            for(int j = 0; j < n; j ++){
                s.append(path[i][j]);
            }
            p.add(s.toString());
        }
        res.add(new ArrayList<>(p));
    }
    public void fun(int n,int row){
        if(row >= n){
            f(n);
            return;
        }
        for(int i = 0; i < n; i ++){
            if(isOk(row,i,n)){
                path[row][i] = 'Q';
                fun(n,row+1);
                path[row][i] = '.';
            }
        }
    }
    public boolean isOk(int r, int l, int n){
        for(int i = 0; i < n; i ++){
            if(path[r][i] == 'Q'){
                return false;
            }
        }
        for(int i = 0; i < n; i ++){
            if(path[i][l] == 'Q'){
                return false;
            }
        }
        for(int i = r-1, j = l-1; i >= 0 && j >= 0;i--,j--){
            if(path[i][j] == 'Q'){
                return false;
            }
        }
        for(int i = r-1, j = l+1; i >= 0 && j <= n-1; i --, j ++){
            if(path[i][j] == 'Q'){
                return false;
            }
        }
        return true;
    }
}

三、力扣37. 解数独

class Solution {
    public void solveSudoku(char[][] board) {
        fun(board);
    }
    public boolean fun(char[][] board){
        for(int i = 0; i < board.length; i ++){
            for(int j = 0; j < board.length; j ++){
                if(board[i][j] != '.'){
                    continue;
                }
                for(char k = '1'; k <= '9'; k ++){
                    if(isOk(board,i,j,k)){
                        board[i][j] = k;
                        if(fun(board)){
                            return true;
                        }
                        board[i][j] = '.';
                    }
                }
                return false;
            }
        }
        return true;
    }
    public boolean isOk(char[][] board, int r, int l, char k){
        for(int i = 0; i < board.length; i ++){
            if(board[r][i] == k){
                return false;
            }
        }
        for(int i = 0; i < board.length; i ++){
            if(board[i][l] == k){
                return false;
            }
        }
        for(int i = r/3*3; i < (r/3+1)*3; i ++){
            for(int j = l/3*3; j < (l/3+1)*3; j ++){
                if(board[i][j] == k){
                    return false;
                }
            }
        }
        return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

乱世在摸鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值