原文链接:【LeetCode学习计划】《数据结构入门-C++》第5天 数组_Wang_Xin_Ling的博客-CSDN博客
目录
36. 有效的数独
LeetCode: 36. 有效的数独
请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
1.数字 1-9 在每一行只能出现一次。
2.数字 1-9 在每一列只能出现一次。
3.数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
方法:哈希表
可以为每一行、每一列和每一个3x3的宫设置一个哈希表,一共是9+9+9=27个哈希表。遍历九宫格的过程中,记录一个元素时需要在它所对应的行、列和宫的哈希表中记录,一个元素一共记录3次。
由于我们一般是按照一行一行地去遍历,所以可以把行哈希表缩减为一个,也就是每一行遍历完后重置哈希表。这样哈希表就变为了1+9+9=19个。
1.
int boxes[3][3][9] = {} 九子宫 一共9元素
2.
const int index = board[i][j] - '0' - 1;
1对应字符‘0’
3.
row[index] == 1 || columns[j][index] == 1 || boxes[i / 3][j / 3][index] == 1
就是意味着之前出现了一次了 (因为1对应 字符‘0’)
4.
row[index]++;
columns[j][index]++;
boxes[i / 3][j / 3][index]++;
计数的过程
#include <vector>
using namespace std;
class Solution
{
public:
bool isValidSudoku(vector<vector<char>> &board)
{
int columns[9][9] = {};
int boxes[3][3][9] = {};
for (int i = 0; i < 9; i++)
{
int row[9] = {};
for (int j = 0; j < 9; j++)
{
if (board[i][j] != '.')
{
const int index = board[i][j] - '0' - 1;
if (row[index] == 1 || columns[j][index] == 1 || boxes[i / 3][j / 3][index] == 1)
return false;
row[index]++;
columns[j][index]++;
boxes[i / 3][j / 3][index]++;
}
}
}
return true;
}
};
73. 矩阵置零
LeetCode: 73. 矩阵置零
给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地算法。
方法1:使用标记数组
假设matrix
的行数为m
,列数为n
,我们可以设置一个m
长的row
和n
长的col
作为标记数组,用于标记每一行、每一列是否有零出现。
我们先完整遍历一次matrix
,记录哪里有零;最后根据row
和col
数组将matrix
对应的行和列全部置零。
#include <vector>
using namespace std;
class Solution
{
public:
void setZeroes(vector<vector<int>> &matrix)
{
const int m = matrix.size(),n = matrix[0].size();
bool *row = new bool[m]{},*col = new bool[n]{};
for (int i = 0;i<m;i++)
{
for (int j = 0;j < n;j++)
{
if (matrix[i][j] == 0)
{
row[i] = true;
col[j] = true;
}
}
}
for (int i = 0;i < m;i++)
{
for (int j = 0;j < n;j++)
{
if (row[i] || col[j])
{
matrix[i][j] = 0;
}
}
}
}
};
方法2:使用2个标记变量
我们可以用矩阵的第一行和第一列来代替方法1中的标记数组,如果某一行某一列存在0,那么就将原矩阵的第一行和第一列对应的位置置零,这样就能剩下两个额外的数组开销了,并且空间复杂度降为了O ( 1 )
不过这样一来,矩阵的第一行第一列原来有没有0就不清楚了,如果第一行或第一列本来就有0的话,最后要把它们单独置零,因此需要两个标记变量分别表示第一行和第一列原先是否含0。
方法2的步骤如下:
标记第一行和第一列中是否含有零。
遍历整个数组,发现0时,更新第一行和第一列对应的位置为零。
通过第一行和第一列去更新整个数组若第一行或第一列本身含有零,那么单独为第一行或第一列置零。
#include <vector>
using namespace std;
class Solution
{
public:
void setZeroes(vector<vector<int>> &matrix)
{
int m = matrix.size(), n = matrix[0].size();
bool row0Has0 = false, col0Has0 = false;
// 设第0行和第0列为标记量
for (int j = 0; j < n; j++)
{
if (matrix[0][j] == 0)
{
row0Has0 = true;
break;
}
}
for (int i = 0; i < m; i++)
{
if (matrix[i][0] == 0)
{
col0Has0 = true;
break;
}
}
// 更新标记量
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
if (matrix[i][j] == 0)
{
matrix[0][j] = matrix[i][0] = 0;
}
}
}
// 使用标记量去更新矩阵
for (int j = 1; j < n; j++)
{
if (matrix[0][j] == 0)
{
for (int i = 1; i < m; i++)
{
matrix[i][j] = 0;
}
}
}
for (int i = 1; i < m; i++)
{
if (matrix[i][0] == 0)
{
for (int j = 1; j < n; j++)
{
matrix[i][j] = 0;
}
}
}
if (row0Has0)
{
for (int j = 0; j < n; j++)
{
matrix[0][j] = 0;
}
}
if (col0Has0)
{
for (int i = 0; i < m; i++)
{
matrix[i][0] = 0;
}
}
}
};