目录
- [36. 有效的数独](#36. 有效的数独)
- [54. 螺旋矩阵](#54. 螺旋矩阵)
- [48. 旋转图像](#48. 旋转图像)
- [73. 矩阵置零](#73. 矩阵置零)
- [289. 生命游戏](#289. 生命游戏)
36. 有效的数独
请你判断一个 9 x 9
的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
数字 1-9
在每一行只能出现一次。
数字 1-9
在每一列只能出现一次。
数字 1-9
在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
注意 :
一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
空白格用 '.'
表示。
示例 1:
输入:board =
[["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:
输入:board =
[["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 存在, 因此这个数独是无效的。
提示 :
board.length == 9
board[i].length == 9
board[i][j]
是一位数字(1-9
)或者 '.'
思路:统计数字的出现次数,一旦出现超过一次,就失败。注意这个题不需要判断题是否有解。
cpp
class Solution {
public:
bool isValidSudoku(vector<vector<char>>& board) {
int rows[9][9] = {0};
int cols[9][9] = {0};
int inside[9][9] = {0};
for(int i = 0; i < 9; i ++){
for(int j = 0; j < 9; j++){
if(board[i][j] < '0' || board[i][j] > '9') continue;
int num = board[i][j] - '0';
//行
if(rows[i][num - 1] > 0){
return false;
}else{
rows[i][num - 1] ++;
}
//列
if(cols[j][num - 1] > 0){
return false;
}else{
cols[j][num - 1] ++;
}
//内
if(inside[(i/3)*3 + j/3][num - 1] > 0){
return false;
}else{
inside[(i/3)*3 + j/3][num - 1] ++;
}
}
}
return true;
}
};
54. 螺旋矩阵
给你一个 m
行 n
列的矩阵 matrix
,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例 1 :
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2 :
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
提示 :
m == matrix.length
n == matrix[i].length
1 <= m, n <= 10
-100 <= matrix[i][j] <= 100
思路:一圈圈来
cpp
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int row = matrix.size(), col = matrix[0].size();
int circle = min((row + 1) / 2, (col + 1) / 2);
vector<int> temp, rec;
for(int i = 0; i < circle; i++){
temp = one_circle(matrix ,row, col, i);
rec.insert(rec.end(), temp.begin(), temp.end());
}
return rec;
}
vector<int> one_circle(vector<vector<int>>& matrix, int row, int col, int circle){
int i = circle, j = circle;
vector<int> rec;
rec.push_back(matrix[i][j]);
while(j < col - circle - 1){ //向右
j ++;
rec.push_back(matrix[i][j]);
}
while(i < row - circle - 1){ //向下
i ++;
rec.push_back(matrix[i][j]);
}
while(row - circle * 2 >= 2 && j > circle){ //向左(如果行是1,就不走了)
j --;
rec.push_back(matrix[i][j]);
}
while(col - circle * 2 >= 2 && i > circle + 1){ //向上(如果列是1,就不走了)
i --;
rec.push_back(matrix[i][j]);
}
return rec;
}
};
48. 旋转图像
给定一个 n × n
的二维矩阵 matrix
表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例 1 :
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]
示例 2 :
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
提示 :
n == matrix.length == matrix[i].length
1 <= n <= 20
-1000 <= matrix[i][j] <= 1000
思路:四角旋转
cpp
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int row = matrix.size();
int circle = ceil((row + 1) / 2);
for(int i = 0; i < circle; i ++){
turn_one_circle(matrix, row, i);
}
}
void turn_one_circle(vector<vector<int>>& matrix, int row, int circle){
int temp;
row -= 1;
for(int i = 0; i < row - circle * 2; i++){
temp = matrix[circle][circle + i];
matrix[circle][circle + i] = matrix[row - circle - i][circle];
matrix[row - circle - i][circle] = matrix[row - circle][row - circle - i];
matrix[row - circle][row - circle - i] = matrix[circle + i][row - circle];
matrix[circle + i][row - circle] = temp;
}
}
};
也可以先水平旋转,再主对角线旋转
73. 矩阵置零
给定一个 m x n
的矩阵,如果一个元素为 0
,则将其所在行和列的所有元素都设为 0
。请使用 原地 算法。
示例 1 :
输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]
示例 2 :
输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]
提示 :
m == matrix.length
n == matrix[0].length
1 <= m, n <= 200
-231 <= matrix[i][j] <= 231 - 1
思路:使用标记数组,一个记录行,一个记录列
cpp
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int m = matrix.size(), n = matrix[0].size();
vector<int> row(m);
vector<int> col(n);
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(matrix[i][j] == 0){
row[i] = 1;
col[j] = 1;
}
}
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(row[i] == 1 || col[j] == 1){
matrix[i][j] = 0;
}
}
}
}
};
289. 生命游戏
根据 百度百科 , 生命游戏 ,简称为 生命 ,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
给定一个包含 m × n
个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态: 1
即为 活细胞 (live),或 0
即为 死细胞 (dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
- 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
- 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
- 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
- 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你 m x n
网格面板 board
的当前状态,返回下一个状态。
示例 1 :
输入:board = [[0,1,0],[0,0,1],[1,1,1],[0,0,0]]
输出:[[0,0,0],[1,0,1],[0,1,1],[0,1,0]]
示例 2 :
输入:board = [[1,1],[1,0]]
输出:[[1,1],[1,1]]
提示 :
m == board.length
n == board[i].length
1 <= m, n <= 25
board[i][j]
为 0
或 1
思路:使用额外的数组
cpp
class Solution {
public:
void gameOfLife(vector<vector<int>>& board) {
int m = board.size(), n = board[0].size();
int rec[m][n];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
int live = live_cell(board, i, j);
if(board[i][j] == 1){
if(live < 2) rec[i][j] = 0;
if(live == 2 || live == 3) rec[i][j] = 1;
if(live > 3) rec[i][j] = 0;
}else{
if(live == 3){
rec[i][j] = 1;
}else{
rec[i][j] = 0;
}
}
}
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
board[i][j] = rec[i][j];
}
}
}
int live_cell(vector<vector<int>> board, int now_i, int now_j){
int m = board.size(), n = board[0].size();
int row[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int col[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
int count = 0;
for(int k = 0; k < 8; k++){
if(now_i + row[k] >= 0 && now_i + row[k] < m && now_j + col[k] >= 0 && now_j + col[k] < n){
if(board[now_i + row[k]][now_j + col[k]] == 1){
count ++;
}
}
}
return count;
}
};
思路 :不使用额外的数组,但是使用额外的标记,-1
本死但活,2
本活但死
cpp
class Solution {
public:
void gameOfLife(vector<vector<int>>& board) {
int m = board.size(), n = board[0].size();
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
int live = live_cell(board, i, j);
if(board[i][j] == 1){
if(live < 2) board[i][j] = 2;
if(live == 2 || live == 3) board[i][j] = 1;
if(live > 3) board[i][j] = 2;
}else{
if(live == 3){
board[i][j] = -1;
}else{
board[i][j] = 0;
}
}
}
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(board[i][j] == -1) board[i][j] = 1;
if(board[i][j] == 2) board[i][j] = 0;
}
}
}
int live_cell(vector<vector<int>> board, int now_i, int now_j){
int m = board.size(), n = board[0].size();
int row[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int col[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
int count = 0;
for(int k = 0; k < 8; k++){
if(now_i + row[k] >= 0 && now_i + row[k] < m && now_j + col[k] >= 0 && now_j + col[k] < n){
if(board[now_i + row[k]][now_j + col[k]] >= 1){
count ++;
}
}
}
return count;
}
};