【LeetCode51】-N皇后

方法一

实现思路

首先理解一个皇后的攻击范围(以四皇后为例,红色箭头为皇后攻击范围)
在攻击范围内的格子是不能放别的皇后的
在这里插入图片描述
放皇后的思路:
一、 遍历每一行,在每一行中特定列中放置皇后
这么遍历的好处是肯定保证了同一行中只有一个皇后,将问题转换为了选择不发生冲突的列

二、 在没有可以选择的列中放置皇后
这里可以选择的列要满足两个条件:

  • 本列之前没有放过皇后
  • 放在此行此列(x,y)不在其他皇后(xi,yi)的对角线上
    • 两个位置(x1,y1),(x2,y2)在同一个斜线满足的条件为
      abs(x1-x2)=abs(y1-y2)

三、 放置的过程中,发现往下走并不可以,回到第二步新选择一个列

四、 发现皇后全部放置完,且符合规则,保存结果


求解实现的函数

  1. 判断当前位置是否和之前的皇后在同一位置上
  2. 回溯生成各个皇后放置的位置
  3. 将位置信息转换为题目要求的字符串格式

实现代码

class Solution {
    
    
public:
    bool attack(int x,int y,vector<int> &put){
    
    
        for(int i=0;i<put.size();i++){
    
    
            if(put[i]!=-1&&abs(x-i)==abs(y-put[i])) return true;
        }
        return false;
    }
    void generate(int x,int n,vector<int> &put,vector<int> & book,vector<vector<int>> &re){
    
    
        
        //x,y均从0开始
        if(x==n){
    
    
            re.push_back(put);
            return;
        }
        for(int y=0;y<n;y++){
    
    
            if(!book[y]&&(!attack(x,y,put))){
    
    
                book[y]=1;
                put[x]=y;
                
                generate(x+1,n,put,book,re);
                
                book[y]=0;
                put[x]=-1;
            }
        }
    }

    void int2string(int n,vector<vector<int>> &re,vector<vector<string>> &re_string){
    
    
        for(int i=0;i<re.size();i++){
    
    
            vector<string> vs;
            for(int j=0;j<n;j++)
            {
    
    
                string s(n,'.');
                s[re[i][j]]='Q';
                vs.push_back(s);
            }
            re_string.push_back(vs);
        }
    }
    vector<vector<string>> solveNQueens(int n) {
    
    
        vector<int> put(n,-1);
        vector<int> book(n,0);
        vector<vector<int>> re;
        vector<vector<string>> re_string;
        generate(0,n,put,book,re);
        int2string(n,re,re_string);
        return re_string;
    }
};

提交结果及分析

在这里插入图片描述
如果从状态空间解的角度来看的话,N皇后问题的时间复杂度是O(N!),但在算法的实现过程中,并非真的第一个皇后放置后,下一个皇后尝试N-1个位置,经历了一个剪枝的过程,在已放置皇后攻击范围内的位置是不会被尝试的

方法二

实现思路

总的思路还是回溯,不同于在于放置皇后之后,多了一步标记不能被放置的位置(为实现这个单独实现了一个函数)
在这里插入图片描述

在这里插入图片描述

实现代码

标记不能走的位置
在这里插入图片描述在这里插入图片描述在这里插入图片描述

总结

我觉得我的第一种方法,要比参考别人的第二种方法效率更高,第二种方法多了一步用mark标记的过程,我取而代之的方法只需要利用下标根据斜线的规律计算一下即可,效率及实现更简洁高效

猜你喜欢

转载自blog.csdn.net/weixin_44944046/article/details/113825330