【算法 C】Leetcode 36. Valid Sudoku 有效的数独
其实算法并没有太难,无论是3次遍历还是1次遍历,都不会超时,我在做的时候,如何使用测试数据反而困扰了我很久。
读取测试数据
将测试数据放在文件中读取,这里将文件指针改为stdin
应该也是一样的效果。
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int boardSize = 9;
int boardColSize = 9;
char** board = (char **) malloc(sizeof(char *) * boardSize);
// 打开文件
FILE *fp = fopen("sudoku1.txt", "r");
if (fp == NULL)
{
fprintf(stderr, "读取文件出错");
exit(-1);
}
// 输出文件内容
printf("文件内容为:\n");
int ch;
while ((ch = fgetc(fp)) != EOF)
{
putchar(ch);
}
printf("\n");
// 读取数组
rewind(fp);
for (int i = 0; i < boardSize; i++)
{
board[i] = (char *) malloc(sizeof(char) * boardSize); // 每行分配内存
for (int j = 0; j < boardColSize; j++)
{
while ((ch = fgetc(fp)) != EOF && ch != '\"');
board[i][j] = fgetc(fp);
fgetc(fp);
}
}
fclose(fp);
// 输出查看数组
printf("读取到数组为: \n");
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardColSize; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
// solve
bool validate = isValidSudoku(board, boardSize, &boardColSize);
puts(validate ? "true": "false");
// 释放内存
for (int i = 0; i < boardSize; i++)
{
free(board[i]);
}
free((void *) board);
return 0;
}
3次遍历
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
bool isValidSudoku(char** board, int boardSize, int* boardColSize)
{
int nums[10] = {0};
int tmp;
// 检查行
for(int i = 0; i < boardSize; i++)
{
memset(nums, 0, sizeof(int) * 10);
for(int j = 0; j < *boardColSize; j++)
{
tmp = board[i][j];
if (tmp <= '9' && tmp > '0')
{
tmp = board[i][j] - '0';
nums[tmp] += 1;
if (nums[tmp] > 1)
{
// printf("false原因(行): [%d, %d]", i, j);
return false;
}
}
}
}
// 检查列
for(int j = 0; j < *boardColSize; j++)
{
memset(nums, 0, sizeof(int) * 10);
for(int i = 0; i < boardSize; i++)
{
tmp = board[i][j];
if (tmp <= '9' && tmp > '0')
{
tmp = board[i][j] - '0';
nums[tmp] += 1;
if (nums[tmp] > 1)
{
// printf("false原因(列): [%d, %d]", i, j);
return false;
}
}
}
}
// 检查九宫格
for (int i = 0; i < boardSize / 3; i++)
{
for (int j = 0; j < *boardColSize / 3; j++)
{
memset(nums, 0, sizeof(int) * 10);
for (int k = 0; k < 3; k++)
{
for (int l = 0; l < 3; l++)
{
tmp = board[i * 3 + k][j * 3 + l];
if (tmp <= '9' && tmp > '0')
{
tmp = tmp - '0';
nums[tmp] += 1;
if (nums[tmp] > 1)
{
// printf("false原因9: [%d, %d]", i * 3 + k, j * 3 + l);
return false;
}
}
}
}
}
}
return true;
}
int main()
{
int boardSize = 9;
int boardColSize = 9;
char** board = (char **) malloc(sizeof(char *) * boardSize);
// 打开文件
FILE *fp = fopen("sudoku1.txt", "r");
if (fp == NULL)
{
fprintf(stderr, "读取文件出错");
exit(-1);
}
// 输出文件内容
printf("文件内容为:\n");
int ch;
while ((ch = fgetc(fp)) != EOF)
{
putchar(ch);
}
printf("\n");
// 读取数组
rewind(fp);
for (int i = 0; i < boardSize; i++)
{
board[i] = (char *) malloc(sizeof(char) * boardSize); // 每行分配内存
for (int j = 0; j < boardColSize; j++)
{
while ((ch = fgetc(fp)) != EOF && ch != '\"');
board[i][j] = fgetc(fp);
fgetc(fp);
}
}
fclose(fp);
// 输出查看数组
printf("读取到数组为: \n");
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardColSize; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
// solve
bool validate = isValidSudoku(board, boardSize, &boardColSize);
puts(validate ? "true": "false");
// 释放内存
for (int i = 0; i < boardSize; i++)
{
free(board[i]);
}
free((void *) board);
return 0;
}
一次遍历
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
bool isValidSudoku(char** board, int boardSize, int* boardColSize)
{
/* 一次遍历 */
int row[9][9] = {0};
int col[9][9] = {0};
int box[9][9] = {0};
int boxIndex;
int tmp;
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
tmp = board[i][j];
if (tmp >='1' && tmp <= '9')
{
tmp -= '1';
boxIndex = (i / 3) * 3 + j / 3;
row[i][tmp] += 1;
col[j][tmp] += 1;
box[boxIndex][tmp] += 1;
if (row[i][tmp] > 1 || col[j][tmp] > 1 || box[boxIndex][tmp] > 1)
{
return false;
}
}
}
}
return true;
}
int main()
{
int boardSize = 9;
int boardColSize = 9;
char** board = (char **) malloc(sizeof(char *) * boardSize);
// 打开文件
FILE *fp = fopen("sudoku1.txt", "r");
if (fp == NULL)
{
fprintf(stderr, "读取文件出错");
exit(-1);
}
// 输出文件内容
printf("文件内容为:\n");
int ch;
while ((ch = fgetc(fp)) != EOF)
{
putchar(ch);
}
printf("\n");
// 读取数组
rewind(fp);
for (int i = 0; i < boardSize; i++)
{
board[i] = (char *) malloc(sizeof(char) * boardSize); // 每行分配内存
for (int j = 0; j < boardColSize; j++)
{
while ((ch = fgetc(fp)) != EOF && ch != '\"');
board[i][j] = fgetc(fp);
fgetc(fp);
}
}
fclose(fp);
// 输出查看数组
printf("读取到数组为: \n");
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardColSize; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
// solve
bool validate = isValidSudoku(board, boardSize, &boardColSize);
puts(validate ? "true": "false");
// 释放内存
for (int i = 0; i < boardSize; i++)
{
free(board[i]);
}
free((void *) board);
return 0;
}