代码随想录day30 回溯算法最终章

文章讲述了如何通过回溯算法解决n皇后问题和数独问题,涉及三维数组、列/行/九宫格条件判断以及递归策略。作者分析了两种问题的相似性和解决步骤,并提供了对应的C++代码实现。
摘要由CSDN通过智能技术生成

51. N皇后

题目

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

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

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

示例 1:

  • 输入:n = 4
  • 输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
  • 解释:如上图所示,4 皇后问题存在两个不同的解法。

思考

看到题就懵了,感觉和之前做的回溯算法完全不一样,这是真的开放性的题,开了卡哥的视频大概梳理出来了一些思路:

1、要创建的结果数组是三维的,因为棋盘是二维的,要存放棋盘

2、因为棋盘是n*n的,那么当纵向递归遍历到n时,收获结果

3、单层递归其实没啥难度,主要是判断当满足题意三个条件时才能纵向递归,注意这里要因为是在二维数组里递归,那么横向遍历的i和纵向递归遍历其实没啥关系,不用startIndex,直接row+1即可

4、满足的三个条件怎么写:

  • 不能同一列出现两个Q,即col不变,判断从0到row的所有数是否有Q
  • 不能45度出现Q,即3,3到2,2到1,1或者3,2到2,1不能出出现Q,row-1,col-1即可
  • 不能135度出现Q,出3,3到2,4到1,5不能出现Q,row-1,col+1即可

代码

class Solution {

public:

    vector<vector<string>> res;

    void backTracking(vector<string>& chess, int n, int row){

        if(row == n) {

            res.push_back(chess);

            return;

        }

        for(int col = 0; col < n; col++) {

            if(isValid(row, col, chess, n)){

                chess[row][col] = 'Q';

                backTracking(chess, n, row+1);

                chess[row][col] = '.';

            }

        }

    }

    bool isValid(int row, int col, vector<string> chess, int n ) {

        for(int i = 0; i < row; i++) {

            if(chess[i][col] == 'Q') return false;

        }

        for(int i = row-1, j = col-1; i>=0 && j>=0; i--&j--) {

            if(chess[i][j]== 'Q') return false;

        }

        for(int i = row -1, j = col+1; i>=0 && j<n; i-- && j++) {

            if(chess[i][j] == 'Q') return false;

        }

        return true;

    }

    vector<vector<string>> solveNQueens(int n) {

        vector<string> chess(n, string(n, '.'));

        backTracking(chess, n, 0);

        return res;

    }

};

37. 解数独

题目

编写一个程序,通过填充空格来解决数独问题。

一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 空白格用 '.' 表示。

解数独

一个数独。

解数独

答案被标成红色。

提示:

  • 给定的数独序列只包含数字 1-9 和字符 '.' 。
  • 你可以假设给定的数独只有唯一解。
  • 给定数独永远是 9x9 形式的。

思考

太难了,感觉和n皇后是差不多的,也是三个条件,但是具体应该怎么写完全一头雾水,看完卡哥视频稍微总结一下吧:

  1. 上来不是void函数,是bool类型的,直接遍历,i<9,j<9
  2. 当board[i][j] =='.'时,说明需要填充数字,开始循环判断1-9中哪个数字满足条件,如果满足,直接填上
  3. 注意,这里的中止条件竟然在填充完数字后,如果填充了,那么判断整个函数是否为true,如果为true,返回true
  4. 如果1-9中数字不满足条件,那么要return false
  5. 三个条件写法
  • 纵向判断要填充的数字是否已经在那一列里
  • 横向判断要填充的数字是否已经在那一行里
  • 在3*3的九宫格里判断要填充的数字是否在九宫格里,用两个for循环,并且startRow和StartCol需要用(row/3)*3来表示

代码

class Solution {

private:

    bool backTracking(vector<vector<char>>& board) {

        for(int i = 0; i < board.size(); i++) {

            for(int j = 0; j < board.size(); j++) {

                if(board[i][j] == '.') {

                    for(char k = '1'; k <= '9'; k++) {

                        if(isValid(i, j, k, board)) {

                            board[i][j] = k;

                            bool tmp = backTracking(board);

                            if(tmp) return true;

                            board[i][j] = '.';

                        }

                    }

                    return false;

                }

            }

        }

        return true;

    }

    bool isValid(int row, int col, char val, vector<vector<char>>& board) {

        for(int i = 0; i < 9; i++) {

            if(board[row][i] == val) return false;

        }

        for(int j = 0; j < 9; j++) {

            if(board[j][col] == val) return false;

        }

        int startRow = (row/3) * 3;

        int startCol = (col/3) * 3;

        for(int i = startRow; i < startRow+3; i++) {

            for(int j = startCol; j < startCol+3; j++) {

                if(board[i][j] == val) return false;

            }

        }

        return true;

    }

public:

    void solveSudoku(vector<vector<char>>& board) {

        backTracking(board);

    }

};

  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值