Leetecode 36 37 Sudoku问题

 首先了解什么是sudoku,见http://sudoku.com.au/TheRules.aspx

即在9X9棋盘里,每一行都要包括1-9数字,每个数字只能出现一次不能重复;每一列都要包括1-9数字,每个数字只能出现一次不能重复;每个3x3小宫格要包括1-9数字,每个数字只能出现一次不能重复。

36. Valid Sudoku
主要是对已有的一个9X9棋盘(部分填充数字,没有数字的单元格有‘.’填充),判断是否满足sudoku定义:即对每一行。每一列和每个小宫格看有没有重复的,对于行和列的判断很简单,关键在于小宫格的判断:

对于给定9X9棋盘,规定坐标:

  0     1    2    3    4     5   6     7    8

         
         
         
         
         
         
         
         
         
则有9个九宫格每个格点的坐标:

行号规律:

第0个九宫格:000111222; 第1个九宫格:000111222; 第2个九宫格:000111222;

第3个九宫格:333444555; 第4个九宫格:333444555; 第5个九宫格:333444555;

第6个九宫格:666777888; 第7个九宫格:666777888; 第8个九宫格:666777888;

列号规律:

第0个九宫格:012012012; 第1个九宫格:345345345; 第2个九宫格:678678678;

第3个九宫格:012012012; 第4个九宫格:345345345; 第5个九宫格:678678678;

第6个九宫格:012012012; 第7个九宫格:345345345; 第8个九宫格:678678678;

第 i 个九宫格里面的第 j 个元素在原矩阵的第 3*(i/3) + j/3 行,第 3*(i%3) + j%3)列,(i和j从0开始)

bool isValidSudoku(vector<vector<char>>& board){

       int i,j;
       for(i=0;i<9;i++){
	   map<char,bool>m1;
	   map<char,bool>m2;
	   map<char,bool>m3;
	   for(j=0;j<9;j++){
	   if(board[i][j]!='.'){if(m1[board[i][j]]==true)return false;
	                         m1[board[i][j]]=true;//第一次出现
	                       }
	   if(board[j][i]!='.'){if(m2[board[j][i]]==true)return false;
	                         m2[board[j][i]]=true;
	                        }
	   if(board[i/3*3+j/3][i%3*3+j%3]!='.'){if(m3[board[i/3*3+j/3][i%3*3+j%3]]==true)return false;
	                                          m3[board[i/3*3+j/3][i%3*3+j%3]]=true;
	                                        }
	                   }
                        }
       return true;
 }
37. Sudoku Solver
对部分填充的sudoku填完,使成为一个sudoku。

类似N-Queen问题,采用回溯法,

需要注意的区别是:

本题找到解的处理是return true,因此返回值为bool

N-Queen找到解的处理是保存解,因此返回值为void

对于每个空位'.',遍历1~9,check合理之后往下一个位置递归。由于这里路径尝试本质上是有序的,即1~9逐个尝试,因此无需额外设置状态位记录已经尝试过的方向,如果该空格无论设置什么数字都无法达到合法状态,那么回溯重新设置上一个空格。

bool checkValidSudoku(vector< vector<char> >& board,int i,int j){
    for(int k=0;k<9;k++)
	if(k!=j&&board[i][k]==board[i][j])return false;
    for(int k=0;k<9;k++)
	if(k!=i&&board[k][j]==board[i][j])return false;
    for(int row=i/3*3;row<i/3*3+3;row++)
    {
	for(int col=j/3*3;col<j/3*3+3;col++)
	    if((row!=i||col!=j)&&board[row][col]==board[i][j])return false;
    }//i,j所在grid的其他坐标位置,不同于36题
    return true;
                                                              }
bool helper_sudoku(vector< vector<char> >& board){
for(int i=0;i<9;i++)
    for(int j=0;j<9;j++)
	if(board[i][j]=='.'){
	    for(int k=1;k<=9;k++)
	    {board[i][j]=k+'0';
		if(checkValidSudoku(board,i,j)&&helper_sudoku(board))return 1;
	    board[i][j]='.';
	    }
	    return 0;

	                     }
return 1;
                                                              }
void solveSudoku(vector< vector<char> > &board){
    helper_sudoku(board);
                                               }






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值