36. 有效的数独
判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。
上图是一个部分填充的有效的数独。
数独部分空格内已填入了数字,空白格用 '.'
表示。
示例 1:
输入:
[
["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:
输入:
[
["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 存在, 因此这个数独是无效的。
说明:
- 一个有效的数独(部分已被填充)不一定是可解的。
- 只需要根据以上规则,验证已经填入的数字是否有效即可。
- 给定数独序列只包含数字
1-9
和字符'.'
。 - 给定数独永远是
9x9
形式的。
class Solution {
public:
bool isValidSudoku(vector<vector<char>>& board) {
for(int i=0;i<9;i++){
int row[9]={0};
int col[9]={0};
int cube[9]={0};
for(int j=0;j<9;j++){
if(board[i][j]!='.'){
if(row[board[i][j]-'1']==1) return false;
else row[board[i][j]-'1']=1;
}
if(board[j][i]!='.'){
if(col[board[j][i]-'1']==1) return false;
else col[board[j][i]-'1']=1;
}
int cubeX=3*(i/3)+j/3;
int cubeY=3*(i%3)+j%3;
if(board[cubeX][cubeY]!='.'){
if(cube[board[cubeX][cubeY]-'1']==1) return false;
else cube[board[cubeX][cubeY]-'1']=1;
}
}
}
return true;
}
};
37. 解数独
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。
空白格用 '.'
表示。
一个数独。
答案被标成红色。
Note:
- 给定的数独序列只包含数字
1-9
和字符'.'
。 - 你可以假设给定的数独只有唯一解。
- 给定数独永远是
9x9
形式的。
class Solution {
public:
int row[9][10];
int column[9][10];
int grid[9][10];
int flag=0;
void solve(int r,int c,vector<vector<char>>& board)
{
int i;
if(r==9) {
flag=1;
return;
}
if(board[r][c]=='.') {
for(i=1;i<=9;i++) {
if(row[r][i]==0&&column[c][i]==0&&grid[3*(r/3)+c/3][i]==0){
board[r][c]=i+'0';
row[r][i]=1;
column[c][i]=1;
grid[3*(r/3)+c/3][i]=1;
if(c==8) solve(r+1,0,board);
else solve(r,c+1,board);
if(flag==1) return;
board[r][c]='.';
row[r][i]=0;
column[c][i]=0;
grid[3*(r/3)+c/3][i]=0;
}
}
}
else{
if(c==8) solve(r+1,0,board);
else solve(r,c+1,board);
}
}
void solveSudoku(vector<vector<char>>& board) {
int i,j,k;
for(i=0;i<9;i++){
for(j=0;j<10;j++)
row[i][j]=column[i][j]=grid[i][j]=0;
}
for(i=0;i<9;i++){
for(j=0;j<9;j++){
if(board[i][j]!='.'){
k=board[i][j]-'0';
row[i][k]=1;
column[j][k]=1;
grid[(i/3)*3+j/3][k]=1;
}
}
}
solve(0,0,board);
}
};
38. 报数
数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1
被读作 "one 1"
("一个一"
) , 即 11
。11
被读作 "two 1s"
("两个一"
), 即 21
。21
被读作 "one 2"
, "one 1"
("一个二"
, "一个一"
) , 即 1211
。
给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。
注意:整数顺序将表示为一个字符串。
示例 1:
输入: 1
输出: "1"
示例 2:
输入: 4
输出: "1211"
class Solution {
public:
string countAndSay(int n) {
string res="1",temp="";
for(int i=1;i<n;i++)
{
int t=0;
while(t<res.length())
{
int num=1;
while(res[t]==res[t+1]&&(t+1)<res.length())
{
num++;
t++;
}
temp=temp+to_string(num)+res[t];
t++;
}
res=temp;
temp="";
}
return res;
}
};
39. 组合总和
给定一个无重复元素的数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的数字可以无限制重复被选取。
说明:
- 所有数字(包括
target
)都是正整数。 - 解集不能包含重复的组合。
示例 1:
输入: candidates =[2,3,6,7],
target =7
, 所求解集为: [ [7], [2,2,3] ]
示例 2:
输入: candidates = [2,3,5],
target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<vector<int>> res;
vector<int> tmp;
findAll(candidates, res,tmp,target,0);
return res;
}
void findAll(const vector<int>& candidates, vector<vector<int>>& res, vector<int>& tmp, int target, int index)
{
if (target == 0) {
res.push_back(tmp);
return;
}
if (target < candidates[0]){
return;
}
for(int i = index; i < candidates.size(); ++i){
tmp.push_back(candidates[i]);
findAll(candidates, res, tmp, target-candidates[i],i);
temp.pop_back();
}
}
};
40. 组合总和 II
给定一个数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用一次。
说明:
- 所有数字(包括目标数)都是正整数。
- 解集不能包含重复的组合。
示例 1:
输入: candidates =[10,1,2,7,6,1,5]
, target =8
, 所求解集为: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
vector<vector<int>> res;
vector<int> tmp;
find(candidates,tmp,res,target,0);
return res;
}
void find(vector<int>& candidates,vector<int>& tmp,vector<vector<int>>& res,int target,int index){
for(int i=index;i<candidates.size();i++){
if(target==candidates[i]){
tmp.push_back(candidates[i]);
res.push_back(tmp);
tmp.pop_back();
return;
}
if(target<candidates[i]){
return;
} else {
tmp.push_back(candidates[i]);
find(candidates,tmp,res,target-candidates[i],i+1);
tmp.pop_back();
while(i<candidates.size()-1 && candidates[i]==candidates[i+1]){
i++;
}
}
}
}
};
(以上题目均摘自leetcode)