logseq_notes/pages/OJ notes/pages/Leetcode Valid-Sudoku.md
2023-06-14 14:27:22 +08:00

5.9 KiB

Leetcode Valid-Sodoku

2022-06-13 12:56


Data structures:

#DS #vector

Difficulty:

#leetcode #coding_problems #difficulty_easy

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

**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
**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:

int usedRow[9][10] = {};
int usedCol[9][10] = {};
int usedGrid[9][10] = {};

Solution

My new solution using hash map

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 :(

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;
}
};