LeetCode Algorithm 0036 - 0040
0036 - Valid Sudoku (Medium)
Problem Link: https://leetcode.com/problems/valid-sudoku/description/
Description
Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules :
-
1. Each row must contain the digits
1-9
without repetition. -
2. Each column must contain the digits
1-9
without repetition. -
3. 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 C++
#pragma once
#include "pch.h"
// Problem: https://leetcode.com/problems/valid-sudoku/description/
namespace P36ValidSudoku
{
class Solution
{
public:
bool isValidSudoku(vector<vector<char>>& board)
{
if (board.empty())
{
return false;
}
// 这个解决方案,可以通过LeetCode,但一些数独结果是错误的。
// 例如:
//
// [[".",".",".", ".",".",".", "1",".","."]
// ,[".",".",".", ".",".",".", ".",".","."]
// ,[".",".",".", ".",".",".", ".",".","."]
//
// ,[".",".",".", ".",".",".", ".","2","."]
// ,[".",".",".", ".",".",".", ".","3","."]
// ,[".",".",".", ".",".",".", ".","4","."]
//
// ,[".",".",".", ".",".",".", ".",".","."]
// ,[".",".",".", ".",".",".", ".",".","."]
// ,[".",".",".", ".",".",".", ".",".","1"]]
//
// 本代码是true,LeetCode的官方答案运行结果也是true
// 但实际上这是一个不合格的数独,结果应该是false
// row num
bool usedRows[9][9] = { false };
// col num
bool usedCols[9][9] = { false };
// cube num
bool usedCubes[9][9] = { false };
for (int r = 0; r < board.size(); r++)
{
for (int c = 0; c < board[r].size(); c++)
{
if (board[r][c] == '.')
{
continue;
}
// 检测的数字
int checkNum = board[r][c] - '0' - 1;
// 第几个九宫格
int cubeIndex = r / 3 * 3 + c / 3;
// 数字是否已经存在
if (usedRows[r][checkNum]
|| usedCols[c][checkNum]
|| usedCubes[cubeIndex][checkNum])
{
return false;
}
usedRows[r][checkNum] = true;
usedCols[c][checkNum] = true;
usedCubes[cubeIndex][checkNum] = true;
}
}
return true;
}
};
}
0037 - Sudoku Solver (Hard)
Problem Link: https://leetcode.com/problems/sudoku-solver/description/
Description
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules :
-
1. Each of the digits
1-9
must occur exactly once in each row. -
2. Each of the digits
1-9
must occur exactly once in each column. -
3. 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 C++
#pragma once
#include "pch.h"
// Problem: https://leetcode.com/problems/sudoku-solver/description/
namespace P37SudokuSolver
{
class Solution
{
public:
void solveSudoku(vector<vector<char>>& board)
{
if (board.empty() || board.size() != 9 || board[0].size() != 9)
{
return;
}
// 空白处的行列坐标
vector<pair<int, int>> noNumIndexes;
// 数独是否有效
bool usedRows[9][9] = { false };
bool usedCols[9][9] = { false };
bool usedCubes[9][9] = { false };
if (!isValidSudoku(board, usedRows, usedCols, usedCubes, noNumIndexes))
{
return;
}
// 计算结果
solving(board, usedRows, usedCols, usedCubes, noNumIndexes, 0);
}
private:
// 计算数独递归
bool solving(vector<vector<char>>& board,
bool usedRows[9][9],
bool usedCols[9][9],
bool usedCubes[9][9],
vector<pair<int, int>>& noNumIndexes, // 空白处的行列坐标
int curNoNumIndex)
{
if (curNoNumIndex == noNumIndexes.size())
{
return true;
}
// 在board中的行列
pair<int, int> index = noNumIndexes[curNoNumIndex];
// 第几个九宫格
int cubeIndex = index.first / 3 * 3 + index.second / 3;
// 可以填入的数字集合
unordered_set<int> numSet = unordered_set<int>();
for (int num = 0; num < 9; num++)
{
if (usedRows[index.first][num]
|| usedCols[index.second][num]
|| usedCubes[cubeIndex][num])
{
continue;
}
numSet.insert(num);
}
// 没有可以填入的数字
if (numSet.size() == 0)
{
return false;
}
// 开始计算:挨个填入可用数字
for (int num : numSet)
{
usedRows[index.first][num] = true;
usedCols[index.second][num] = true;
usedCubes[cubeIndex][num] = true;
board[index.first][index.second] = (char)(num + 1 + '0');
if (solving(board, usedRows, usedCols, usedCubes, noNumIndexes, curNoNumIndex + 1))
{
return true;
}
// 填入的数字有错误
usedRows[index.first][num] = false;
usedCols[index.second][num] = false;
usedCubes[cubeIndex][num] = false;
}
return false;
}
// 本函数修改来自36,函数bug参考36注释
// 检测数独是否有效
bool isValidSudoku(vector<vector<char>>& board,
bool usedRows[9][9],
bool usedCols[9][9],
bool usedCubes[9][9],
vector<pair<int, int>>& noNumIndexes)
{
for (int r = 0; r < board.size(); r++)
{
for (int c = 0; c < board[r].size(); c++)
{
if (board[r][c] == '.')
{
noNumIndexes.push_back(pair<int, int>(r, c));
continue;
}
int checkNum = board[r][c] - '0' - 1;
int cubeIndex = r / 3 * 3 + c / 3;
if (usedRows[r][checkNum]
|| usedCols[c][checkNum]
|| usedCubes[cubeIndex][checkNum])
{
return false;
}
usedRows[r][checkNum] = true;
usedCols[c][checkNum] = true;
usedCubes[cubeIndex][checkNum] = true;
}
}
return true;
}
};
}
0038 - Count and Say (Easy)
Problem Link: https://leetcode.com/problems/count-and-say/description/
Description
The count-and-say sequence is the sequence of integers with the first five terms as following:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1
is read off as "one 1"
or 11
.
11
is read off as "two 1s"
or 21
.
21
is read off as "one 2, then one 1"
or 1211
.
Given an integer n where 1 ≤ n ≤ 30, generate the nth term of the count-and-say sequence.
Note: Each term of the sequence of integers will be represented as a string.
Example 1:
Input: 1
Output: "1"
Example 2:
Input: 4
Output: "1211"
Solution C++
#pragma once
#include "pch.h"
// Problem: https://leetcode.com/problems/count-and-say/description/
namespace P38CountAndSay
{
class Solution
{
public:
string countAndSay(int n)
{
// 题目意思就是,每次输出上一次出现数字的个数。
// 1. 1 1
// 2. 11 一个1
// 3. 21 两个1
// 4. 1211 一个2,一个1
// 5. 111221 一个1,一个2,2个1
// 不符合要求的数字
if (n < 1 || n > 30)
{
return "-1";
}
if (n == 1)
{
return "1";
}
string last = countAndSay(n - 1);
string cur = "";
for (size_t i = 0; i < last.size(); i++)
{
if (cur == "" || last[i] != cur.back())
{
cur += "1";
cur += last[i];
}
else
{
int index = cur.size() - 2;
cur[index] += 1;
}
}
return cur;
}
};
}
0039 - Combination Sum (Medium)
Problem Link: https://leetcode.com/problems/combination-sum/description/
Description
Given a set of candidate numbers (candidates
) ( without duplicates ) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sums to target
.
The same repeated number may be chosen from candidates
unlimited number of times.
Note:
- All numbers (including
target
) will be positive integers. - The solution set must not contain duplicate combinations.
Example 1:
Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
[7],
[2,2,3]
]
Example 2:
Input: candidates = [2,3,5], target = 8,
A solution set is:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
Solution C++
#pragma once
#include "pch.h"
// Problem: https://leetcode.com/problems/combination-sum/description/
namespace P39CombinationSum
{
class Solution
{
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target)
{
vector<vector<int>> results;
vector<int> result;
combinationSumInternal(candidates, target, results, result, 0);
return results;
}
private:
void combinationSumInternal(vector<int>& candidates,
int target,
vector<vector<int>>& results,
vector<int>& result,
int startIndex)
{
for (int i = 0; i < candidates.size(); i++)
{
int sub = target - candidates[i];
if (sub < 0)
{
continue;
}
result.push_back(candidates[i]);
if (sub == 0)
{
results.push_back(result);
}
else
{
combinationSumInternal(candidates, sub, results, result, i);
}
result.pop_back();
}
}
};
}
0040 - Combination Sum II (Medium)
Problem Link: https://leetcode.com/problems/combination-sum-ii/description/
Description
Given a set of candidate numbers (candidates
) ( without duplicates ) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sums to target
.
Each number in candidates
may only be used once in the combination.
Note:
- All numbers (including
target
) will be positive integers. - The solution set must not contain duplicate combinations.
Example 1:
Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
Example 2:
Input: candidates = [2,5,2,1,2], target = 5,
A solution set is:
[
[1,2,2],
[5]
]
Solution C++
#pragma once
#include "pch.h"
// Problem: https://leetcode.com/problems/combination-sum-ii/description/
namespace P40CombinationSumII
{
class Solution
{
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target)
{
vector<vector<int>> results;
vector<int> result;
sort(candidates.begin(), candidates.end());
combinationSumInternal(candidates, target, results, result, 0);
return results;
}
private:
void combinationSumInternal(vector<int>& candidates,
int target,
vector<vector<int>>& results,
vector<int>& result,
int startIndex)
{
for (int i = startIndex; i < candidates.size(); i++)
{
if (i > startIndex && candidates[i] == candidates[i - 1])
{
continue;
}
int sub = target - candidates[i];
if (sub < 0)
{
continue;
}
result.push_back(candidates[i]);
if (sub == 0)
{
results.push_back(result);
}
else
{
combinationSumInternal(candidates, sub, results, result, i + 1);
}
result.pop_back();
}
}
};
}