Leetcode算法题51 N-Queen解法代码及思路(C++)

2 篇文章 0 订阅
1 篇文章 0 订阅

Leetcode算法题51 N-Queen解法代码及思路(C++)

原题:

算法结果:

个人思路

1.分析限定条件

限定条件是每,每斜线不能有超过 1 个皇后,而且对于 n*n 的棋盘,要放入 n 个皇后,因此每都必然有 1 个皇后,而且每只有 1 个。

2.循环

由于每必然都有 1 个皇后,我们可以从第 1 列开始,判断每列的皇后在第几行,来决定整个棋盘皇后的摆放。其中只需要注意判断新的皇后在不在之前皇后所在的,以及在不在之前皇后所在的斜线上即可。(两处的代码分别见注释1注释2

3.列的变化

每次如果新的皇后没有和之前的斜线有冲突,那么列+1
如果新的皇后和之前的斜线有冲突,那么行+1,也就是尝试将这个皇后摆到更高的行。
最后需要注意的是当皇后的超过n(代码中行列0开始,所以此处是超过n-1)时,将列-1,同时将该的棋子上移一行,来尝试新的可能性。

4.时间复杂度

本题的时间复杂度必然比较高,因此尽可能降低每个棋子每次试探的判别次数。
最差情况下时间复杂度是O(nn)
使用了n=4,6,8,10进行了测试,
实际的时间复杂度大约在4*O(nn/2)

代码

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        int map[n]; //记录每列的皇后分别在第几行
        vector<vector<string>> output;
        vector<string> solution;

        bool ld[n*2-1];//left diagonal左对角线
        bool rd[n*2-1];//right diagonal右对角线
        int i,j;
        int o1,o2;
        string temp = "";
        for(i = 0; i< n; i ++)
        {
            temp +='.';
        }
        if(n==1)
        {
            solution.push_back("Q");
            output.push_back(solution);
            return output;
        }
        for(i = 0; i< n*2-1; i ++)
        {
            ld[i] = false;//false 表示该对角线未被使用
            rd[i] = false;
        }
        map[0] = 0;
        i = 0;
        while(true)
        {
            if(map[i] == n)
            {
                i--;
                if(i<0)
                    break;
                ld[map[i]+i] = false;
                rd[map[i]+n-1-i] = false;
                map[i]++;
                continue;
            }
            bool jump = false;
            for(j = 0;j <i; j++)  //注释1:   判断是否和之前已经摆放的皇后同行  
            {
                if(map[i] == map[j])
                {
                    map[i]++;
                    jump = true;
                    break;
                }
            }
            if(jump)
                continue;
            if(ld[map[i]+i] | rd[map[i]+n-1-i])   //注释2:  判断所在的两条对角线是否被使用
            {
                map[i]++;
                continue;
            }
            
            if(i == n-1)
            {
                solution.clear();
                for(o1 = n-1; o1 >= 0 ; o1--)
                {
                    string temp2 = temp;
                    for(o2 = 0; o2 < n ; o2++)
                    {
                        if(map[o2] == o1)
                            temp2[o2] = 'Q';
                    }
                    solution.push_back(temp2);  
                }
                output.push_back(solution);
                i--;
                ld[map[i]+i] = false;
                rd[map[i]+n-1-i] = false;
                map[i]++;
                continue;
            }
            
            ld[map[i]+i] = true;
            rd[map[i]+n-1-i] = true;
            i++;            
            map[i] = 0;
        }
        return output;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值