n皇后问题javascript所有解(非递归)

leetcode-n皇后

https://leetcode-cn.com/problems/n-queens/

思路:先用回溯法求得第一组解,然后检查最后一行下一列是否满足。

从上到下,从左向右枚举。后面的解的列靠近右边。当然也可以从右到左枚举。从中间向两边枚举

function queen(n) {

                if(n === 1) {
                    return [["Q"]]
                    
                }
                let i = 0;
                let arr = [];
                //保存皇后放在那列的索引
                for(let k = 0; k < n; k++) {
                    arr.push(0);
                }
                let isOk = true;
                while(i < n) {

                    let solve = true;
                    //let j = arr[r];
                    for(let j = arr[i]; j < n; j++) {
                        //检查该处皇后是否不被上面行的皇后攻击
                        let a = checkLeftTop(i, j, arr);
                        let b = checkTop(i, j, arr);
                        let c = checkRightTop(i, j, n, arr);

                        solve = a && b && c;
                        if(solve) {
                            //放这行皇后的列位置
                            arr[i] = j;
                            break;
                        }
                    }
                    //此行所有位置都不满足,回溯到祖先行
                    if(solve === false) {
                        let info = back(i, arr, n);
                        if(info.status) {
                            i = info.row;
                            continue;
                        } else {
                            //第一行全都遍历不满足,无解
                            console.log(info);
                            console.error("no solve");
                            isOk = false;
                            break;
                        }
                    }
                    i++;
                }
                
                if(isOk === false){
                    return [];
                }
                let result = [];
                let firstGroup = [];
                for(let i = 0;i<n;i++){
                    firstGroup.push(arr[i]);
                }
                result.push(firstGroup);
                let step = true;
                while (step){
                    let next = other(n, arr);
                    //console.log(next);
                    if(Array.isArray(next)){
                        let otherGroup = [];
                        for(let i = 0;i<n;i++){
                            otherGroup.push(arr[i]);
                        }
                        result.push(otherGroup);
                    }
                    else{
                        step = false;
                    }
                }
                //result.push(firstGroup);
                //let next = other(n, arr);
                console.log(result.length);
                let answer = [];
                for(let group of result){
                    
                    let s = formatQueen(group,n);
                    answer.push(s);
                    
                }
                //console.log(answer);
                return answer;
            }
            /**
             * 不被攻击true
             * @param {number} i row
             * @param {number} j column
             * @param {array} a 
             * @returns boolean
             */
            function checkLeftTop(i, j, a) {
                for(let m = i - 1, n = j - 1; m >= 0 && n >= 0; m--, n--) {
                    //a[m] 上行皇后所在列
                    if(a[m] === n) {
                        return false;
                    }
                }
                return true;
            }

            function checkTop(i, j, a) {
                for(let m = i - 1; m >= 0; m--) {
                    if(a[m] === j) {
                        return false;
                    }
                }
                return true;
            }

            function checkRightTop(i, j, colNum = 8, a) {

                for(let m = i - 1, n = j + 1; m >= 0 && n < colNum; m--, n++) {
                    if(a[m] === n) {
                        return false;
                    }
                }
                return true;
            }

            /**
             * back parent row
             * @param {number} i row
             * @param {array} a 
             * @param {number} rowNum 
             * @returns 
             */
            function back(i, a, rowNum) {

                let status = false;
                //回溯列
                let row = i;
                //console.log(i,a);
                for(let r = i - 1; r >= 0; r--) {
                    if(a[r] < rowNum - 1) {
                        a[r] = a[r] + 1;
                        //回到上一行
                        row = r;
                        status = true;
                        //清空数据
                        for(let m = r + 1; m < rowNum; m++) {
                            a[m] = 0;
                        }
                        break;
                    }
                }
                return {
                    status,
                    row
                }
            }
            /**
             *下一组解,从最后一行回溯
             * @param {number} n 
             * @param {array} arr 前一组解
             * @returns 
             */
         

function other(n, arr) {
                let column = arr[n-1];
                let i = n - 1;
                //console.log(column);
                if(column === n - 1) {
                    let info = back(n - 1, arr, n);
                    if(info.status) {
                        i = info.row;
                        //console.log(i);
                    } else {
                        console.log(info);
                        return;
                    }
                }
                else{
                    //last row next column;
                    arr[i] = arr[i] + 1;
                }
                
                let isOk = true;
                while(i < n) {

                    let solve = true;
                    //let j = arr[r];
                    for(let j = arr[i]; j < n; j++) {
                        
                        let a = checkLeftTop(i, j, arr);
                        let b = checkTop(i, j, arr);
                        let c = checkRightTop(i, j, n, arr);

                        solve = a && b && c;
                        if(solve) {
                            arr[i] = j;
                            break;
                        }
                    }
                    //此行所有位置都不满足,回溯到祖先行
                    if(solve === false) {
                        let info = back(i, arr, n);
                        if(info.status) {
                            i = info.row;
                            continue;
                        } else {
                            //第一行全都遍历不满足,无解
                            //console.log(info);
                            console.error("no solve");
                            isOk = false;
                        }
                    }
                    i++;
                }
                if(isOk){
                    return arr;
                }
                

            }


            
            function formatQueen(arr,n){
                let result = [];
                for(let i = 0; i < n;i++){
                    
                    let row = [];
                    let index = arr[i];
                    for(let j = 0;j < n;j++){
                        if(j === index){
                            row.push("Q")
                        }
                        else{
                            row.push(".")
                        }
                    }
                    let str = row.join("");
                    result.push(str);
                }
                return result;
            }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值