# Leetcode Valid-Sodoku #### 2022-06-13 12:56 --- ##### Data structures: #DS #vector ##### Difficulty: #leetcode #coding_problem #difficulty_easy ##### Related topics: ##### Links: - [Link to problem](https://leetcode.com/problems/valid-sudoku/) - [Simple solution]() --- ### Problem Determine if a `9 x 9` 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 nine `3 x 3` sub-boxes of the grid must contain the digits `1-9` without repetition. **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. #### Examples ![[Pasted image 20220613125739.png]] ```markdown **Input:** 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"]] **Output:** true ``` ```markdown **Input:** 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"]] **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. ``` #### Constraints - board.length == 9 - board[i].length == 9 - board[i][j] is a digit `1-9` or `'.'`. ### Thoughts This should be a follow-up of [[Leetcode Reshape-The-Matrix]], I tried to implement using unordered set, but regular arrays should suffice. Besides overthinking, I also spent a lot of time learning how to use sets and init multi-dimensional vectors. **Take TWO:** Use a hash table to store whether an element is present: ```cpp int usedRow[9][10] = {}; int usedCol[9][10] = {}; int usedGrid[9][10] = {}; ``` ### Solution My new solution using hash map ```cpp class Solution { public: bool isValidSudoku(vector> &board) { // from 0 to 9 int usedRow[9][10] = {}; int usedCol[9][10] = {}; int usedGrid[9][10] = {}; int grid; int boardVal; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { grid = i / 3 * 3 + j / 3; boardVal = board[i][j]; if (boardVal == '.') { continue; } boardVal = boardVal - '0'; if (usedRow[i][boardVal] || usedCol[j][boardVal] || usedGrid[grid][boardVal]) { return false; } usedRow[i][boardVal]++; usedCol[j][boardVal]++; usedGrid[grid][boardVal]++; } } return true; } }; ``` Bad solution :( ```cpp class Solution { public: bool isValidSudoku(vector> &board) { // store info as unordered_set // even(it % 2 == 0): // horizontal // odd(it % 2 == 1): // vertical vector>>> sets(9); for (int i = 0; i < 9; i++) { sets[i] = vector>>(2); for (int j = 0; j < 2; j++) { sets[i][j] = vector>(3); } } for (int i = 0; i < 9; i++) { // populate set[i][0], horizontal for (int j = 3 * (i / 3); j < 3 * (i / 3) + 3; j++) { // iterate rows for (int k = 3 * (i % 3); k < 3 * (i % 3) + 3; k++) { // iterate over cols if (board[j][k] >= '0' && board[j][k] <= '9') { // Insert that if it is a number auto valPair = sets[i][0][j % 3].insert(board[j][k] - '0'); // there is a duplicate if (valPair.second == false) { return false; } } } } // if the whole set is empty bool is_empty = true; for (int j = 0; j < 3; j++) { if (!sets[i][0][j].empty()) { is_empty = false; continue; } } if (is_empty == true) { continue; } // check sets[i][0][*] is legit, and move data to set[i][0][0] unordered_set tmp; for (auto tmpsets : sets[i][0]) { for (int j : tmpsets) { auto result = tmp.insert(j); if (result.second == false) { return false; } } } // populate set[i][0], vertically for (int k = 3 * (i % 3); k < 3 * (i % 3) + 3; k++) { // iterate over cols for (int j = 3 * (i / 3); j < 3 * (i / 3) + 3; j++) { // iterate rows if (board[j][k] >= '0' && board[j][k] <= '9') { // Insert that if it is a number auto valPair = sets[i][1][k % 3].insert(board[j][k] - '0'); // there is a duplicate if (valPair.second == false) { return false; } } } } } // check each row and col. for (int i = 0; i < 9; i++) { for (int k = 0; k < 3; k++) { // check for rows if (i % 3 != 2) { sets[i + 1][0][k].merge(sets[i][0][k]); if (!sets[i][0][k].empty()) { printf("Found at %d\n", i); for (int val : sets[i][0][k]) { printf("%d ", val); } printf("\n"); return false; } } // check for cols if (i < 6) { sets[i + 3][1][k].merge(sets[i][1][k]); if (!sets[i][1][k].empty()) { printf("Found duplicated col at %d, %d\n", i, k); for (int val : sets[i][1][k]) { printf("%d ", val); } printf("\n"); return false; } } } } return true; } }; ```