36. Valid Sudoku
Difficulty: Medium
Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:
- Each row must contain the digits
1-9
without repetition. - Each column must contain the digits
1-9
without repetition. - Each of the 9
3x3
sub-boxes of the grid must contain the digits1-9
without repetition.
A partially filled sudoku which is valid.
The Sudoku board could be partially filled, where empty cells are filled with the character '.'
.
Example 1:
Input:
[
["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"]
]
Output: true
Example 2:
Input:
[
["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"]
]
Output: false
Explanation: Same as Example 1, except with the 5 in the top left corner being
modified to 8\. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
Note:
- A Sudoku board (partially filled) could be valid but is not necessarily solvable.
- Only the filled cells need to be validated according to the mentioned rules.
- The given board contain only digits
1-9
and the character'.'
. - The given board size is always
9x9
.
Solution
Language: C++
class Solution {
public:
bool isValidSudoku(vector<vector<char>>& board) {
vector<vector<int>> rows(9, vector<int>(10, 0));
vector<vector<int>> cols(9, vector<int>(10, 0));
vector<vector<int>> boxes(9, vector<int>(10, 0));
for (int r = 0; r < 9; ++r) {
for (int c = 0; c < 9; ++c) {
if (board[r][c] == '.') {
continue;
}
const int num = board[r][c] - '0';
if (!rows[r][num] && !cols[c][num] && !boxes[r / 3 * 3 + c / 3][num]) {
rows[r][num] = 1;
cols[c][num] = 1;
boxes[r / 3 * 3 + c / 3][num] = 1;
} else {
return false;
}
}
}
return true;
}
};
37. Sudoku Solver
Difficulty: Hard
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules:
- Each of the digits
1-9
must occur exactly once in each row. - Each of the digits
1-9
must occur exactly once in each column. - Each of the the digits
1-9
must occur exactly once in each of the 93x3
sub-boxes of the grid.
Empty cells are indicated by the character '.'
.
A sudoku puzzle…
…and its solution numbers marked in red.
Note:
- The given board contain only digits
1-9
and the character'.'
. - You may assume that the given Sudoku puzzle will have a single unique solution.
- The given board size is always
9x9
.
Solution
Language: C++
class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
rows_ = vector<vector<int>>(9, vector<int>(10));
cols_ = vector<vector<int>>(9, vector<int>(10));
boxes_ = vector<vector<int>>(9, vector<int>(10));
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
const char c = board[i][j];
if (c != '.') {
const int n = c - '0';
const int bx = j / 3;
const int by = i / 3;
rows_[i][n] = 1;
cols_[j][n] = 1;
boxes_[by * 3 + bx][n] = 1;
}
}
}
fill(board, 0, 0);
}
private:
bool fill(vector<vector<char>>& board, int x, int y) {
if (y == 9) {
return true;
}
const int nx = (x + 1) % 9;
const int ny = (nx == 0) ? y + 1 : y;
if (board[y][x] != '.') {
return fill(board, nx, ny);
}
for (int i = 1; i <= 9; ++i) {
const int bx = x / 3;
const int by = y / 3;
const int box_key = by * 3 + bx;
if (!rows_[y][i] && !cols_[x][i] && !boxes_[box_key][i]) {
rows_[y][i] = 1;
cols_[x][i] = 1;
boxes_[box_key][i] = 1;
board[y][x] = i + '0';
if (fill(board, nx, ny)) {
return true;
}
board[y][x] = '.';
boxes_[box_key][i] = 0;
cols_[x][i] = 0;
rows_[y][i] = 0;
}
}
return false;
}
private:
vector<vector<int>> rows_, cols_, boxes_;
};
980. Unique Paths III
Difficulty: Hard
On a 2-dimensional grid
, there are 4 types of squares:
1
represents the starting square. There is exactly one starting square.2
represents the ending square. There is exactly one ending square.0
represents empty squares we can walk over.-1
represents obstacles that we cannot walk over.
Return the number of 4-directional walks from the starting square to the ending square, that walk over every non-obstacle square exactly once.
Example 1:
Input: [[1,0,0,0],[0,0,0,0],[0,0,2,-1]]
Output: 2
Explanation: We have the following two paths:
1\. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2)
2\. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2)
Example 2:
Input: [[1,0,0,0],[0,0,0,0],[0,0,0,2]]
Output: 4
Explanation: We have the following four paths:
1\. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3)
2\. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3)
3\. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3)
4\. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3)
Example 3:
Input: [[0,1],[2,0]]
Output: 0
Explanation:
There is no path that walks over every empty square exactly once.
Note that the starting and ending square can be anywhere in the grid.
Note:
1 <= grid.length * grid[0].length <= 20
Solution
Language: C++
class Solution {
public:
int uniquePathsIII(vector<vector<int>>& grid) {
rows_ = static_cast<int>(grid.size());
if (rows_ == 0) {
return 0;
}
cols_ = static_cast<int>(grid[0].size());
if (cols_ == 0) {
return 0;
}
num_of_non_obstacle_ = 0;
// find start pos
for (int r = 0; r < rows_; ++r) {
for (int c = 0; c < cols_; ++c) {
if (grid[r][c] != -1) {
++num_of_non_obstacle_;
}
if (grid[r][c] == 1) {
start_r = r;
start_c = c;
}
}
}
// depth-first search
sum_ = 0;
dfs(grid, start_r, start_c, 1);
return sum_;
}
private:
void dfs(vector<vector<int>>& grid, const int r, const int c, const int cnt) {
if (r < 0 || r >= rows_ || c < 0 || c >= cols_ || grid[r][c] == -1) {
// if out of bounds, or already there
return;
}
if (grid[r][c] == 2) {
if (cnt == num_of_non_obstacle_) {
++sum_;
}
return;
}
const int backup = grid[r][c];
grid[r][c] = -1;
dfs(grid, r - 1, c, cnt + 1);
dfs(grid, r + 1, c, cnt + 1);
dfs(grid, r, c - 1, cnt + 1);
dfs(grid, r, c + 1, cnt + 1);
grid[r][c] = backup;
}
private:
int rows_;
int cols_;
int start_r, start_c;
size_t num_of_non_obstacle_;
int sum_;
};