# 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](<https://leetcode.com/problems/valid-sudoku/discuss/15464/My-short-solution-by-C%2B%2B.-O(n2)>)

---

### 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<vector<char>> &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<vector<char>> &board) {
    // store info as unordered_set
    // even(it % 2 == 0):
    // horizontal
    // odd(it % 2 == 1):
    // vertical
    vector<vector<vector<unordered_set<int>>>> sets(9);
    for (int i = 0; i < 9; i++) {
      sets[i] = vector<vector<unordered_set<int>>>(2);
      for (int j = 0; j < 2; j++) {
        sets[i][j] = vector<unordered_set<int>>(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<int> 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;
  }
};

```
