有效的数独

题目

判断一个9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。
数字?1-9?在每一行只能出现一次。
数字?1-9?在每一列只能出现一次。
数字?1-9?在每一个以粗实线分隔的?3x3?宫内只能出现一次。
上图是一个部分填充的有效的数独。
数独部分空格内已填入了数字,空白格用?’.’?表示。
示例?1:
输入:
[
[“5”,“3”,".",".",“7”,".",".",".","."],
[“6”,".",".",“1”,“9”,“5”,".",".","."],
[".",“9”,“8”,".",".",".",".",“6”,"."],
[“8”,".",".",".",“6”,".",".",".",“3”],
[“4”,".",".",“8”,".",“3”,".",".",“1”],
[“7”,".",".",".",“2”,".",".",".",“6”],
[".",“6”,".",".",".",".",“2”,“8”,"."],
[".",".",".",“4”,“1”,“9”,".",".",“5”],
[".",".",".",".",“8”,".",".",“7”,“9”]
]
输出: true
示例2:
输入:
[
? [“8”,“3”,".",".",“7”,".",".",".","."],
? [“6”,".",".",“1”,“9”,“5”,".",".","."],
? [".",“9”,“8”,".",".",".",".",“6”,"."],
? [“8”,".",".",".",“6”,".",".",".",“3”],
? [“4”,".",".",“8”,".",“3”,".",".",“1”],
? [“7”,".",".",".",“2”,".",".",".",“6”],
? [".",“6”,".",".",".",".",“2”,“8”,"."],
? [".",".",".",“4”,“1”,“9”,".",".",“5”],
? [".",".",".",".",“8”,".",".",“7”,“9”]
]
输出: false
解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。
但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
说明:
一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
给定数独序列只包含数字?1-9?和字符?’.’?。
给定数独永远是9x9形式的。

分析

	1.其实思路很简单,根据题目要求我们可以发现其实是需要判断三个条件:
	 (1)判断每一行是否有重复字符
	 (2)判断每一列是够有重复字符
	 (3)判断每一个3*3九宫格是否存在重复
	2.上面做法时间和内存消耗都会比较好,下面注释的做法时间会和上面这种差不多,但是内存消耗会比下面的
	  这种做法小一些。
	3.checkout[3 * (i / 3) + j / 3][num]这个操作其实就是判断九宫格,但是虽然行是3,但是列是9


下面这种是最优解
#include<iostream>
#include<string>
#include<vector>

using namespace std;

class MyClass
{
public:
	bool isValidSudoku(vector<vector<char>>& board) {
		if (board.empty()){
			return false;
		}

		vector<vector<int>> checkout(9,vector<int>(9,0));
		vector<vector<int>> row(9, vector<int>(9, 0));
		vector<vector<int>> col(9, vector<int>(9, 0));
		for (int i = 0; i < board.size(); ++i){
			for (int j = 0; j < board[0].size(); ++j){
				if (board[i][j] != '.'){
					int num = board[i][j] - '0' - 1;
					++row[i][num];
					++col[j][num];
					++checkout[3 * (i / 3) + j / 3][num];
					if (row[i][num] == 2 || col[j][num] == 2 || checkout[3 * (i / 3) + j / 3][num] == 2){
						return false;
					}
				}
			}
		}
		return true;
	}
};

下面这种方法比较好理解

	bool isValidSudoku(vector<vector<char>>& board) {
		int len=9;
		//判断每一行是否满足
		for(int i=0;i<len;++i)
		{
			if(isRowValid(i,board)==false)
			return false;
		}
		//判断每一列是否满足
		for(int i=0;i<len;++i)
		{
			if(isColumnValid(i,board)==false)
			return false;
		}
		//判断每一个格子是否满足,每一次找到一个九宫格的左上角位置,以次为基准开始判断
		for (int i = 0; i<len; i += 3)
		{
			for (int j = 0; j<len; j += 3)
			{	
				if (isNineValid(i, j, board) == false)
				return false;
			}
		}
		return true;
	}

	bool isRowValid(int row, vector<vector<char>>& board)//判断单独一行是否有效
	{
		vector<char> temp;
		for (int i = 0; i<board[0].size(); ++i)
		{
			if ('.' == board[row][i])
				continue;
			else
			{
				temp.push_back(board[row][i]);
			}

			//判断最后push进的元素是否与前面的相同,因为是先push,后比较,所以要小于size()-1
			for (int j = 0; j<temp.size() - 1; ++j)
			{
				if (temp[j] == board[row][i])
					return false;
			}
		}
		return true;
	}

	bool isColumnValid(int column, vector<vector<char>>& board)//判断每一列是否有效
	{
		vector<char> temp;
		for (int i = 0; i<board[0].size(); ++i)
		{
			if (board[i][column] == '.')
				continue;
			else
			{
				temp.push_back(board[i][column]);
			}

			//判断最后push进的元素是否与前面的相同,因为是先push,后比较,所以要小于size()-1
			//之所以每次对比是因为这样可以发现重复及时退出,而且这样才能判断有无重复,否则全部压进去,
			  无法比较
			for (int j = 0; j<temp.size() - 1; ++j)
			{
				if (temp[j] == board[i][column])
					return false;
			}
		}
		return true;
	}

	//判断单独一个九宫格是否有效
	bool isNineValid(int row, int column, vector<vector<char>>& board)
	{
		vector<char> temp;
		for (int i = row; i < row + 3; ++i)
		{
			for (int j = column; j < column + 3; ++j)
			{
				if (board[i][j] == '.')
					continue;
				else
				{
					temp.push_back(board[i][j]);
				}
				for (int k = 0; k < temp.size() - 1; ++k)
				{
					if (temp[k] == board[i][j])
						return false;
				}
			}
		}
		return true;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值