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
)或者'.'
这一道题目每遍历到一个数字,都要进行相应的判断,所以用哈希表来记录每个数字的状态是最优解。
每个数字要判断行,列和每个九宫格,所以定义三个二维数组来记录这些状态。
其中最关键的是每个九宫格的判断,要通过计算每个数字的横纵坐标来算出位于哪一个九宫格
bool isValidSudoku(char** board, int boardSize, int* boardColSize) {
int row[9][10] = {0};
int col[9][10] = {0};
int box[9][10] = {0}; //这里将所有位置都初始化零,总共有九行,九列,九个九宫格
int i, j;
for(i = 0; i < boardSize; i++) {
for(j = 0; j < boardColSize[0]; j++) {
if(board[i][j] == '.') {
continue;
}
int num = board[i][j] - '0';
if(row[i][num]) {
return false;
}
if(col[j][num]) {
return false;
}
if(box[i/3 + (j / 3) * 3][num]) { //i/3 + (j / 3) * 3 是用来计算数字属于哪一个九宫格
return false;
}
row[i][num]++;
col[j][num]++;
box[i/3 + (j / 3) * 3][num]++;
}
}
return true;
}
90. 子集 II
给你一个整数数组 nums
,其中可能包含重复元素,请你返回该数组所有可能的
子集
(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
提示:
-
1 <= nums.length <= 10
-
-10 <= nums[i] <= 10
这道题目在返回子集的基础上要去重,去重的操作通过将数组排好序之后再添加相应判断后就可以实现
int** ans;
int anstop;
int* path;
int pathtop;
int* length;
int compare(const void* a, const void* b) {
return *(int*)a - *(int*)b;
}
void backtracking(int* nums, int numsSize, int startindex) {
int* temp = (int*)malloc(sizeof(int) * pathtop); //因为是要返回子集,所以树上每一个节点都要返回
int i;
for(i = 0; i < pathtop; i++) {
temp[i] = path[i];
}
length[anstop] = pathtop;
ans[anstop++] = temp;
if(startindex >= numsSize) {
return;
}
int j;
for(j = startindex; j < numsSize; j++) {
if(j > startindex && nums[j] == nums[j - 1]) { //这部分就是去重的判断,因为之前已经对数组排好序了,这里直接对前一个数进行判断,若是相等,则跳过
continue;
}
path[pathtop++] = nums[j];
backtracking(nums, numsSize, j + 1);
pathtop--;
}
}
int** subsetsWithDup(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
qsort(nums, numsSize, sizeof(int), compare);
path = (int*)malloc(sizeof(int) * numsSize);
ans = (int**)malloc(sizeof(int*) * 100000);
length = (int*)malloc(sizeof(int) * 1500);
anstop = pathtop = 0;
backtracking(nums, numsSize, 0);
*returnSize = anstop;
*returnColumnSizes = (int*)malloc(sizeof(int) * anstop);
int i;
for(i = 0; i < anstop; i++) {
(*returnColumnSizes)[i] = length[i];
}
return ans;
}
*returnColumnSizes = (int*)malloc(sizeof(int) * anstop);
int i;
for(i = 0; i < anstop; i++) {
(*returnColumnSizes)[i] = length[i];
}
return ans;
}