【力扣】数学之美:对角线与N皇后问题的完美结合

对角线性质分析

在这里插入图片描述

在二维数组中:
主对角线(黑色)满足条件:y - x = n,其中 n 是一个固定值,对于同一条主对角线,n 值相同,不同的主对角线 n 值不同。
副对角线(红色)满足条件:y + x = n,其中 n 也是一个固定值,对于同一条副对角线,n 值相同,不同的副对角线 n 值不同。
利用这个特性,可以高效处理某些涉及二维数组对角线的算法问题,而不需要暴力枚举每个元素。

样例分析

力扣-N皇后
对于N皇后问题,我们就可以通过对角线问题巧妙解决。

N 皇后

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位

在这里插入图片描述

解法

首先n×n的棋盘,需要摆放n个皇后,因为皇后可以左右,所以一定是每行一个,可以上下攻击,肯定也是每列一个。因此这2个情况很容易分析,我们只需要每行进行遍历放一个皇后,即可解决左右攻击问题,用个数组来记录哪列放了皇后,即可解决上下攻击问题。关键问题就是斜线,如果暴力解决,花费的时间成本就比较高,我们通过二维数组的横纵坐标的关系,进行解决。
总结一下流程
解法思路
行列攻击限制:
每行只能放置一个皇后,因此可以逐行遍历,每次在当前行放置一个皇后。
用一个数组 col 记录哪些列已经放置过皇后,避免重复。
主副对角线攻击限制:
主对角线:满足 y - x = n,需要额外对负值偏移进行调整,映射到非负下标。
副对角线:满足 y + x = n,直接映射即可。
使用两个数组 dig1 和 dig2 记录主、副对角线是否被占用。
递归搜索:
从第 0 行开始,逐行尝试每个列的位置,验证是否满足列、主对角线、副对角线的限制。
如果满足,将当前皇后放置,递归进入下一行。
如果某次尝试失败(所有列均不满足),回溯上一行进行其他尝试。

参考代码

class Solution {
public:
    vector<bool> col,dig1,dig2;//记录列,主对角线,副对角线。
    vector<vector<string>> ans;//记录结果
    vector<string> path;//记录棋盘
    int _n = 0;
    vector<vector<string>> solveNQueens(int n) {
        _n = n;
        path.resize(n,string(n,'.'));
        col.resize(n,false);
        dig1.resize(n*2,false);//这里就是需要稍微调整的地方,由于数组下标没有负数,所以我们对y-x=b都加上一个n,这样就保证必然是大于0,能够进行映射。
        dig2.resize(n*2,false);//因为x+y可能是n-1+n-1,所以我们开的是2倍n
        dfs(0);
        return ans;
    }

    void dfs(int row)//这个参数表示我们现在处理的是多少行。
    {
        if(row == _n)//这里表示进行到了最后,相当于放成功了
        {
            ans.push_back(path);
            return ;
        }
        for(int i=0;i<_n;i++)//这里就是找可以放皇后的列
        {
            if(!col[i]&&!dig1[row-i+_n]&&!dig2[row+i]) //行可以放,主对角线可以放(意思就是上几行放的皇后的主对角线没有经过这里),副对角线可以放。
            {
                path[row][i] = 'Q';//这里尝试放皇后
                col[i] = dig1[row-i+_n]=dig2[row+i] = true;
                dfs(row+1);//进行下一行的尝试
                path[row][i] = '.';
                col[i] = dig1[row-i+_n]=dig2[row+i] = false;
            }
        }

    }
};

总结

对角线解题的优势
1、减少搜索空间
通过主、副对角线的特性,可以快速判断某位置是否被斜线占用,无需逐一遍历棋盘,极大提高了算法效率。
2、简单的映射关系
使用简单的数学公式(y - x 和 y + x)将二维棋盘的斜线问题转化为一维数组的访问问题,代码实现直观简洁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值