题解 | #N皇后问题#

N皇后问题

https://www.nowcoder.com/practice/c76408782512486d91eea181107293b6

回溯的基本框架:

// 怎么做?
function Nqueen(n) {
    let res = 0;
    
    const backtrack = function (?) {
        // 终止条件是啥
        if (?) {
            res++;
            return;
        }
        // 怎么遍历
        for (?) {
            // 做什么操作?
            ?

            backtrack(board, row + 1);

            // 取消操作
            ?
        }
    };

    backtrack(?);

    return res;
}

module.exports = {
    Nqueen,
};

解题步骤:

  • 问1:思考N皇后问题怎么做?它是在做什么?

答:在 N * N 的棋盘上放置棋子 Q ,Q有个特性就是它会攻击所在行所在列以及斜对角上的棋子。现在要求你在棋盘上放上最多的Q,问你有几种放法。

所以,你需要一个 N * N 的 棋盘 board,记录你的放法。

  • 问2:你会怎么放?

答:第一行先放一个Q,下一行遍历所有的格子,在一个合适的格子上放上Q,然后再到下一行。直到棋盘的最后一行放上了Q,就完成了一种方法。

所以,backtrack的入参是:

const backtrack = function(board, row) {}

终止条件:

if(row === board.length) {
  res++;
  return;
}

每行遍历所有列,在合适的格子上放上Q:

for(let c = 0; c < board[row].length; c++) {
  // 判断当前格子是否合适放置,不合适就不放了
  if(!isvalid(board, row, col)) continue;
  // 做的操作 
  board[row][c] = 'Q';
  
  backtrack(board, row + 1);
  
  // 取消操作
  board[row][c] = '#';
}
  • 问3:怎么判断格子是否合适:

答:当前列有Q不能再放;当前格子左上角有Q不能再放(不只是左上角的一个格子,是整个左上角斜对角线);当前格子右上角有Q不能再放。

伪代码如下:

function isValid(board, row, col) {
  for(let i = 0; i < board.length; i++) {
   if(board[i][col] === 'Q') return false;
  }
  
  for(i = row - 1, j = col - 1; i && j >= 0 ; i--, j--)  {
   if(board[i][j]==='Q') return false;
  }
  
  for(i = row-1, j = col + 1; i && j < bCols; i--,j++) {
   if(board[i][j] === 'Q') return false;
  }
  
  return ture;
}

最终结果:

function Nqueen(n) {
    const board = Array.from(Array(n), () => Array(n).fill("#"));

    let res = 0;

    const backtrack = function (board, row) {
        // 终止条件是啥
        if (row === board.length) {
            res++;
            return;
        }
        // 怎么遍历
        for (let c = 0; c < board[0].length; c++) {
            if (!isValid(board, row, c)) continue;
            // 做什么操作?
            board[row][c] = "Q";

            backtrack(board, row + 1);

            // 取消操作
            board[row][c] = "#";
        }
    };

    backtrack(board, 0);

    return res;
}

function isValid(board, row, col) {
    const n = board.length;

    // 同一列有Q不行
    for (let i = 0; i < n; i++) {
        if (board[i][col] === "Q") {
            return false;
        }
    }

    // 左上角有Q不行
    for (let i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
        if (board[i][j] === "Q") {
            return false;
        }
    }

    // 右上角有Q不行
    for(let i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
        if(board[i][j] === 'Q') {
            return false;
        }
    }

    return true;
}

module.exports = {
    Nqueen,
};

全部评论

相关推荐

06-27 12:54
已编辑
门头沟学院 Java
累了,讲讲我的大学经历吧,目前在家待业。我是一个二本院校软件工程专业。最开始选专业是觉得计算机感兴趣,所以选择了他。本人学习计算机是从大二暑假结束开始的,也就是大三开始。当时每天学习,我个人认为Java以及是我生活的一部分了,就这样持续学习了一年半,来到了大四上学期末,大概是在12月中旬,我终于找的到了一家上海中厂的实习,但我发现实习生的工作很枯燥,公司分配的活也不多,大多时间也是自己在自学。就这样我秋招末才找到实习。时间来到了3月中旬,公司说我可以转正,但是转正工资只有7000,不过很稳定,不加班,双休,因为要回学校参加答辩了,同时当时也是心高气傲,认为可以找到更好的,所以放弃了转正机会,回学校准备论文。准备论文期间就也没有投递简历。然后时间来到了5月中旬,这时春招基本也结束了,然后我开始投递简历,期间只是约到了几家下场面试。工资也只有6-7k,到现在我不知道该怎么办了。已经没有当初学习的心劲了,好累呀,但是又不知道该干什么去。在家就是打游戏,boss简历投一投。每天日重一次。26秋招都说是针对26届的人,25怎么办。我好绝望。要不要参加考公、考研、央国企这些的。有没有大佬可以帮帮我。为什么感觉别人找工作都是顺其自然的事情,我感觉自己每一步都在艰难追赶。八股文背了又忘背了又忘,我每次都花很长时间去理解他,可是现在感觉八股、项目都忘完了。真的已经没有力气再去学习了。图片是我的简历,有没有大哥可以指正一下,或者说我应该走哪条路,有点不想在找工作了。
码客明:太累了就休息一下兄弟,人生不会完蛋的
如果实习可以转正,你会不...
点赞 评论 收藏
分享
程序员小白条:找的太晚,别人都是大三实习,然后大四秋招春招的,你大四下了才去实习,晚1年
点赞 评论 收藏
分享
昨天 13:51
门头沟学院 Java
周五投的,流程今天结束
投递地平线等公司7个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务