最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【Daily Interview】- 21 解数独

    正文概述 掘金(初心Yearth)   2021-01-12   538

    题目

    【Daily Interview】- 21 解数独

    分析

    对数独规则不太清楚的读者可以看看这里:数独。

    同之前的单词搜索和 N 皇后问题类似,数独的解题思路同样简单粗暴:

    • 看看当前位置能不能填
    • 如果可以则填入,继续判断下一个位置
    • 如果遇到死路则退回来填入其他结果

    而这也就是回溯算法的核心了,以数独为例,我们可以看看下面的流程图,方便理解回溯算法:

    【Daily Interview】- 21 解数独

    那么我们可以根据这个套路,完成代码的宏观架构:

    var solveSudoku = function (board) {
      // 遍历棋盘
      for (let i = 0; i < 9; i++) {
        for (let j = 0; j < 9; j++) {
          // 如果当前格子不为 .,说明已经被下过,直接跳过即可
          if (board[i][j] !== ".") continue;
          for (let value = 1; value <= 9; value++) {
            if (canset()) {
              // 更新状态,进入下一步,回退状态
              board[i][j] = value;
              solveSudoku(board);
              board[i][j] = ".";
            }
          }
        }
      }
    };
    

    对于上述代码,不能忘的是考虑边界条件:

    • 何时回退
      • 显然当当前格子所有值都不能填入的时候,就应该回退了,那么应该在遍历完 1~9 的可选值之后返回 false
    • 何时结束
      • 整个棋盘都被填完的时候,这时说明解出答案,就可以结束了,这个时候应该返回 true

    代码如下:

    var solveSudoku = function (board) {
      // 遍历棋盘
      for (let i = 0; i < 9; i++) {
        for (let j = 0; j < 9; j++) {
          // 如果当前格子不为 .,说明已经被下过,直接跳过即可
          if (board[i][j] !== ".") continue;
          for (let value = 1; value <= 9; value++) {
            if (canSet()) {
              // 更新状态,进入下一步,回退状态
              board[i][j] = value;
    +          if (solveSudoku(board)) return true;
              board[i][j] = ".";
            }
          }
    +      return false;
        }
      }
    +  return true;
    };
    

    接下来就是细节上的实现:如何判断当前格子是否能填入对应数字。

    对于这个问题,我们理清规则其实不难:

    • 当前行已经有的所有值都不能与 value 相等
    • 当前列已经有的所有值都不能与 value 相等
    • 当前 3 x 3 的九宫格内所已经有的所有值都不能与 value 相等

    前二者比较简单,只需固定死 row 和 col 即可,而第三个,我们则需要首先找到当前遍历到的格子属于哪一块九宫格。

    这里我们来看一个数独:

    【Daily Interview】- 21 解数独

    可以看到,9 个九宫格将整个 9 x 9 的棋盘分成了 9 块,那么我们完全可以忽略掉小格子,将其转化成 3 x 3 的棋盘。

    const x = Math.floor(row / 3) * 3;
    const y = Math.floor(col / 3) * 3;
    

    这样就可以定位是具体的九宫格了。

    综上,完善 canSet 代码:

    const canSet = (board, row, col, value) => {
      const x = Math.floor(row / 3) * 3;
      const y = Math.floor(col / 3) * 3;
    	
    	// 九宫格内有数字与 value 相等
      for (let i = 0; i < 3; i++) {
        for (let j = 0; j < 3; j++) {
          if (board[x + i][y + j] === value) {
            return false;
          }
        }
      }
    
    	// 行列有数字与 value 相等
      for (let i = 0; i < 9; i++) {
        if (board[row][i] === value || board[i][col] === value) {
          return false;
        }
      }
    
      return true;
    };
    

    结果如下:

    【Daily Interview】- 21 解数独


    起源地下载网 » 【Daily Interview】- 21 解数独

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元