用链表思想解数独

260 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情

前言

给大家分享一个解数独的小算法,数独是每一行每一列,不能出现重复的值,并且每个3*3的格子内的数字也只能出现一次,问题是现在格子内有很多数字存在,现在把不合格的数字给赋值为空

无标题1.png

递归+回溯

  • 遍历 首先需要挨个进行遍历最外层9*9的方格和格子内层数,这样就可以遍历到每一个小方块
  for(var i = 0;i<9;i++){
    for(var l = 0;l<9;i++){}
  }
  • 如果为空 遍历如果每个小方格不能与小数点.(空格用这个表示),那么把该循环结束,继续下次循环
if(tables[y][l]!='.'){continue}

说明:比如说遍历到某一个格子,在内有数字,不能再放数字了,则跳出循环

  • 如果不为空 如果是小数点(空格),则需要两个判定条件:
  1. 判定这个空格子,放数字是否符合数独条件,如果判定允许则把该数字赋值上去,并进行回溯
  for(var k = 1;k<=9;k++){
    if(isNum(y,l,k).toString()){
      shudu[y][l] = k.toString()
      if(sudoKu(shudu)){return true}
      shudu[y][l] = '.'
    }
  }

如果遍历的该数字可以放到方格内,那么就赋值到方格内,随后进行递归,递归结束后,再次进行遍历,如果该数字不能放到方格内,则进行回溯给方格赋值为空格

判定数组能不能放

  function isNum(r,c,k){
    for(let o =0;o<9;o++){
      if(shudu[r][o] === k || shudu[o][c] == k){
        return false
      }
    }
  }

如果没有数字,那么可以在内放1-9内的其中一个数字,循环判定放那个数字合适,如果方格的某行某列的一个数字等于遍历的数字,则相同要继续遍历

  1. 判断3*3小方格的索引值,在那个方格内 首先获取小方格的位置(x轴y轴),循环遍历小方格,如果每个小方格内的数据等与0-9之一,那么则当前数字不符合要求
const X = math.floor(r*3)*3
const Y = math.floor(r*3)*3
  for(let p =0;p<3;p++){
    for(let j =0;j<3;j++){
      if(shudu[X+i][p+j] == k){
        return false
      }
    }
  }

思路:通过回溯和递归形式,判定条件改成了每一行每一列的值和3*3的每一行每列的值