leetcode 36:Valid Sudoku

题目:

Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.

The Sudoku board could be partially filled, where empty cells are filled with the character '.'.


A partially filled sudoku which is valid.

Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.


思路:

先弄清楚题目的意思,题目不是要求我们将数独解出来,也不是判断数独是否有解,而是将判断数独是否合法的,所谓合法,是指每个数字都是1-9,而且每一行,每一列都没有数字重复。大家首先想到的肯定是两个fou循环,逐次判断每行或者每列是否满足。那么如何判断某一行是否有重复呢,如果每个元素都与前面的元素进行比较,将会花费O(n^2*(1+n)*n/2)=O(n^4)天啦,太浪费时间了。

当然我们可以用一个空间复杂度为O(n)的hash表来代替,这样,每次判断是否重复的时间为O(1),总时间为O(n^2)。

我发现我忽略了一点,就是不仅要检测行的重复,还要检测列的重复,如果照上面的时间复杂度,是只检测了行或列的重复,不可取。

既然这样,我们只能定义一个hash表,大小为n*n,来记录行和列的重复,时间复杂度不变。

可惜这种方法也不可取

class Solution {
public:
	bool isValidSudoku(vector<vector<char>>& board) {
		int size = board[0].size();
		vector<vector<int>> hash(size, vector<int>(size, 0));
		for (int i = 0; i < size; i++)
		{
			for (int j = 0; j < size; j++)
			{
				if (board[i][j] == '.') continue;
				if (hash[i][board[i][j]-'0'] == 1) return false;
				hash[i][board[i][j] - '0'] = 1;
				if (hash[board[i][j] - '0'][j] == 1) return false;
				hash[board[i][j] - '0'][j] = 1;
			}
		}
		return true;
	}
};
如果按这样来,由于board[i]的范围在1-9,
hash[board[i][j] - '0'][j]是来判断行是否有重复,可是会覆盖列的hash表,造成误判。
只能用两个不同的hash来了,就不会出现覆盖。
<pre name="code" class="cpp">class Solution {
public:
	bool isValidSudoku(vector<vector<char>>& board) {
		vector<vector<int>> hash1(10, vector<int>(10, 0));
		vector<vector<int>> hash2(10, vector<int>(10, 0));
		for (int i = 0; i < 9; i++)
		{
			for (int j = 0; j < 9; j++)
			{
				if (board[i][j] == '.') continue;
				if (hash1[i][board[i][j]-'0'] == 1) return false;
				hash1[i][board[i][j] - '0'] = 1;
				if (hash2[board[i][j] - '0'][j] == 1) return false;
				hash2[board[i][j] - '0'][j] = 1;
			}
		}
		return true;
	}
};


可惜运行到这个地方出错,我觉得没问题啊,这个数独应该是合法的啊,还望哪个大神知道错在哪里,然后告知,感激不尽!


 补充:原来我漏掉了一个判定条件,就是每个3*3子格的数字都要完全不同。 

下面补上正解:

class Solution
{
public:
	bool isValidSudoku(vector<vector<char> > &board)
	{
		int hash1[9][9] = { 0 }, hash2[9][9] = { 0 }, hash3[9][9] = { 0 };

		for (int i = 0; i < board.size(); ++i)
			for (int j = 0; j < board[i].size(); ++j)
				if (board[i][j] != '.')
				{
					int num = board[i][j] - '0' - 1, k = i / 3 * 3 + j / 3;
					if (hash1[i][num] || hash2[j][num] || hash3[k][num])
						return false;
					hash1[i][num] = hash2[j][num] = hash3[k][num] = 1;
				}

		return true;
	}
};

时间复杂度和空间复杂度均为O(n^2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值