🥳前端算法面试之八皇后--每日一练

前言

今天分享前端面试算法的经典问题--八皇后问题

八皇后问题是一个经典的回溯算法问题。该问题是在一个 8x8 的棋盘上放置 8 个皇后,使得它们彼此不互相攻击,即任意两个皇后都不在同一行、同一列和同一对角线上。这个问题可以用回溯算法解决,即尝试在棋盘上放置皇后,如果发现某位置不合法,就撤销该位置的皇后,并继续尝试下一个位置。

就像下面这样

这张图中的每个棋子就符合八皇后的排列

手动摆貌似可以解决这个问题,但是需要穷尽所有的排列可能,就非人力可为了

解题思路

什么是回溯算法呢?回溯算法是一种解决组合问题(如组合、排列等)的通用算法。它通过不断地尝试和撤销,从问题的初始状态出发,搜索问题的解空间,直到找到一个符合条件的解为止。也就是说 回溯算法的核心思想是"选择-检查-撤销",即在尝试解决一个问题时,先从当前的选择中选择一个方案,然后检查该方案是否满足问题的要求,如果满足,则继续尝试下一个方案;如果不满足,则撤销该方案,回到上一个选择,尝试其他方案。

回到话题,那八皇后可以描述为以下步骤:

  1. 初始化一个 8x8 的棋盘,所有位置都没有放置皇后。
  2. 选择一个位置放置第一个皇后。
  3. 检查该位置是否合法,即是否满足任意两个皇后都不在同一行、同一列和同一对角线上。
  4. 如果该位置合法,则继续尝试下一个位置放置第二个皇后。
  5. 重复步骤 3 和 4,直到放置完所有 8 个皇后。
  6. 如果成功放置了所有 8 个皇后,则输出解决方案。

是不是很简单,对,就是这么简单

代码实现

javascript 复制代码
const eightQueue = (array, line) => {
   // 如果当前行数已经超过数组长度,说明已经找到了一个解决方案
   if (line >= array.length) {
       printQueue(array);
       console.log("------");
       return;
   }
   
   for (let position = 0; position < array.length; position++) {
       // 如果当前位置可以放置皇后,则将其放置到当前行的位置上
       if (isOK(array, line, position)) {
           array[line] = position;
           eightQueue(array, line + 1);
       }
   }
};

const isOK = (array, row, position) => {
   let left = position - 1,
       right = position + 1;
   
   // 从上一行的位置开始,向前遍历每一行
   for (let i = row - 1; i >= 0; i--) {
       // 如果当前位置与当前位置冲突,或者与当前位置的左侧或右侧冲突,则返回 false
       if (array[i] == position) return false;
       if (left >= 0 && array[i] == left) return false;
       if (right < array.length && array[i] == right) return false;
       
       // 更新左右两侧皇后的位置
       left--;
       right++;
   }
   
   // 如果没有冲突,则返回 true
   return true;
};

const printQueue = (array, line = 0) => {
   // 如果当前行数已经超过数组长度,则不需要打印棋盘
   if (line >= array.length) return;
   
   let res = "";
   
   // 打印棋盘
   for (let i = 0; i < array.length; i++) {
       if (array[line] == i) {
           res += "#  ";
       } else {
           res += "-  ";
       }
   }
   
   console.log(res);
   
   // 递归打印下一行的棋盘
   printQueue(array, line + 1);
};

代码中定义了三个函数

  1. eightQueue 函数:定义了一个递归函数,用于解决八皇后问题。输入参数是一个数组 array 和当前处理到的行数 line。
  2. isOK 函数:定义了一个检查当前位置是否可以放置皇后的函数。输入参数是一个数组 array、当前处理到的行数 row 和当前位置 position。
  3. printQueue 函数:定义了一个打印棋盘的函数。输入参数是一个数组 array 和当前处理到的行数 line。

对于每个可以放置皇后的位置,调用 isOK 函数检查该位置是否满足条件。如果满足条件,将该位置放置到当前行的位置上,并递归调用 eightQueue 函数处理下一行。

在 isOK 函数中,首先定义了左右两个皇后位置的索引 left 和 right,初始值分别为 position - 1 和 position + 1。然后,从上一行的位置开始,向前遍历每一行,检查列是否冲突,左上有没有冲突,右上有没有冲突。如果冲突,则返回 false。最后,如果没有冲突,则返回 true

如果当前行数已经超过数组的长度,说明已经找到了一个解决方案,调用 printQueue 函数打印棋盘,并输出一个分隔符 "------"。

测试代码

测试代码看看效果吧

javascript 复制代码
eightQueue(Array(8).fill(-1), 0);

现将所有的数组内容初始化为-1,然后从第 0 行开始调用

这是打印截图。统计了下,共有 92 种排列方式,只能提供一部分截图咯

总结

这篇文章分享了前面面试的经典问题--八皇后。解决问题的思路是不断地"选择-检查-撤销",即在尝试解决一个问题时,先从当前的选择中选择一个方案,然后检查该方案是否满足问题的要求,如果满足,则继续尝试下一个方案;如果不满足,则撤销该方案,回到上一个选择,尝试其他方案。对于八皇后,就是不断地尝试每一个位置,看看可不可行,如果不可行,就放到下一个位置。

你觉得这篇文章怎么样?我每天都会分享一篇算法小练习,喜欢就点赞+关注吧

相关推荐
PP东18 分钟前
ES学习class类用法(十一)
javascript·学习
海威的技术博客22 分钟前
JS中的原型与原型链
开发语言·javascript·原型模式
从以前44 分钟前
【算法题解】Bindian 山丘信号问题(E. Bindian Signaling)
开发语言·python·算法
不白兰1 小时前
[代码随想录23回溯]回溯的组合问题+分割子串
算法
outstanding木槿1 小时前
JS中for循环里的ajax请求不数据
前端·javascript·react.js·ajax
酥饼~1 小时前
html固定头和第一列简单例子
前端·javascript·html
所以经济危机就是没有新技术拉动增长了1 小时前
二、javascript的进阶知识
开发语言·javascript·ecmascript
Bubluu1 小时前
浏览器点击视频裁剪当前帧,然后粘贴到页面
开发语言·javascript·音视频
御风@户外2 小时前
质数生成函数、质数判断备份
算法·acm
han_2 小时前
不是哥们,我的console.log突然打印不出东西了!
前端·javascript·chrome