算法:N皇后问题

这里分享一个经典搜索问题,N皇后。

题目:51. N皇后

链接:51.N皇后

思路分析

思路是很好想的,简单的搜索就行,

首先,我们思考,究竟是一个格子一个格子搜索,还是一行一行搜索呢?

显然一个格子一个格子搜索,递归的深度太夸张了,时间复杂度就变成了2^(N*N),这不可能接收的了,

所以,应该还是一行一行搜索比较合适,

那么搜索一行的时候,应该搜索啥呢?

肯定是要尝试将皇后放在这一行的所有格子上。

OK,那么如何判断是否能放在该格子呢?

也就是如何进行剪枝。

题目提供的剪枝要求是,同一行、同一列、主对角线、副对角线上都不能有其他的皇后。

这里又需要思考一下,真的需要遍历该行、该列、整条对角线吗?

这一个遍历就是O(N)的时间复杂度,也就成了4N (2^N),

虽然在这道题目,也能通过,但是,还可以在优化,

搜索题目里面剪枝的优化,大概率是要使用到hash表的,将遍历检查的O(N)降低到O(1),

所以应该有一个hash表来记录,哪一列有皇后了,哪个对角线有皇后了,

注意,由于我们是按照行搜索的,搜索到当前行,当前行肯定是没有皇后的,也就可以少一个hash表。

列上有皇后很好表示,y相同就行了,

对角线上有皇后怎么表示呢?

我们来看主对角线,

我们会发现,x + 1,y随之+1,所以, x - y = x0 - y0;

再看副对角线,

我们会发现,x + 1,y随之-1,所以,x + y = x0 + y0;

编码细节

我们用vector模拟hash表来存储的时候,

x - y 可能会小于0,也就是说,可能会越界,

所以,处理成x - y + n ,就能保证下标一定 大于0 ,不会越界。

具体代码

c 复制代码
    //n皇后问题思路,对每一行一次进行搜索
    //每一行的每一列都要尝试
    //尝试该位置的时候,需要检查斜线上是否有元素和y上是否有元素,我们是以x为单位进行遍历,所以x不用检查
    //主对角线:x每次++,y随之++,也就是 y - x = y0 - x0
    //副对角线:x每次++,y随之--,也就是 y + x = y0 + x0
    //斜线,y = y0
    //这三个条件只要满足一个,就break,尝试该行中的下一个位置
    
    vector<vector<string>> ret;
    int count = 0;
    void dfs(vector<string> path, vector<int> col, vector<int> dis1, vector<int>dis2)
    {
        if(path.size() == count)
        {
            ret.push_back(path);
            return;
        }
        
        for(int i = 0;i < count;i++)
        {
            int x = path.size();
            int y = i;
         
            // O(N)的时间复杂度剪枝太慢了
            if(col[i] == true) continue;
            if(dis1[x - y + count] == true) continue;
            if(dis2[x + y] == true) continue;
          	 //组织临时字符串
            string tmp;
            for(int j = 0;j < count;++j)
            {
                if(j == i) tmp += 'Q';
                else tmp += '.';
            }
            path.push_back(tmp);
            col[i] = true;
            dis1[x - y + count] = true;
            dis2[x + y] = true;
            
            //递归
            dfs(path,col,dis1,dis2);
            
            //回溯
            col[i] = false;
            dis1[x - y + count] = false;
            dis2[x + y] = false;
            path.pop_back();
        }
    }
    
    vector<vector<string>> solveNQueens(int n) {
        count = n;
        vector<string> path;
        vector<int> col(n,false);
        vector<int> dis1(n * 2,false); // x - y ,可能会越界x < y ,所以计算的是x - y + n
        vector<int> dis2(n * 2,false); // x + y
        dfs(path,col,dis1,dis2);
        return ret;
    }
相关推荐
仰泳的熊猫12 小时前
题目2570:蓝桥杯2020年第十一届省赛真题-成绩分析
数据结构·c++·算法·蓝桥杯
无极低码15 小时前
ecGlypher新手安装分步指南(标准化流程)
人工智能·算法·自然语言处理·大模型·rag
软件算法开发15 小时前
基于海象优化算法的LSTM网络模型(WOA-LSTM)的一维时间序列预测matlab仿真
算法·matlab·lstm·一维时间序列预测·woa-lstm·海象优化
superior tigre16 小时前
22 括号生成
算法·深度优先
努力也学不会java17 小时前
【缓存算法】一篇文章带你彻底搞懂面试高频题LRU/LFU
java·数据结构·人工智能·算法·缓存·面试
旖-旎17 小时前
二分查找(x的平方根)(4)
c++·算法·二分查找·力扣·双指针
ECT-OS-JiuHuaShan18 小时前
朱梁万有递归元定理,重构《易经》
算法·重构
智者知已应修善业18 小时前
【51单片机独立按键控制数码管移动反向,2片74CH573/74CH273段和位,按键按下保持原状态】2023-3-25
经验分享·笔记·单片机·嵌入式硬件·算法·51单片机
khddvbe18 小时前
C++并发编程中的死锁避免
开发语言·c++·算法