Check Sudoku board configuration is valid or not(Using Hashing)

Spread the love

Though with a trade-off in space complexity, this strategy reduces the time complexity of the prior one. For every row, column, and submatrix we track the values we have already seen or visited using an unordered set.

We look for if the current cell value already exists in the matching row, column, or sub-grid as we iterate over the matrix and for each cell. Should a duplicate surface, the Sudoku board is void. The board arrangement is good if, after looking over all the cells, no duplicates are discovered.

Important Observation: The sudoku matrix consists of nine 3x 3 submatrices; so, the formula (i / 3) * 3 + j / 3 will help one to determine the index of a given submatrix.

C++

#include <bits/stdc++.h>
using namespace std;

// Function to check if the Sudoku matrix is valid
int isValid(vector<vector<int>> & mat) {
  
    // Arrays of unordered sets to keep track of seen
    // numbers in rows, columns, and subMatrix
    unordered_set<int> rows[9];
    unordered_set<int> cols[9];
    unordered_set<int> subMat[9];

    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
          
            // Get the value at the current cell
            int val = mat[i][j];

            // For empty (0), skip to the next cell
            if (val == 0) continue;

            // Check if the value already exists
            // in the current row
            if (rows[i].find(val) != rows[i].end()) {
              
                // Duplicate found, return false
                return false;
            }
          
            // Insert the value into the current row's set
            rows[i].insert(val);

            // Check if the value already exists
            // in the current column
            if (cols[j].find(val) != cols[j].end()) {
              
                // Duplicate found, return false
                return false; 
            }
          
            // Insert the value into the current column's set
            cols[j].insert(val);

            // Calculate the index for the 3x3 box
            int idx = (i / 3) * 3 + j / 3;
          
            // Check if the value already exists
            // in the current 3x3 box
            if (subMat[idx].find(val) != subMat[idx].end()) {
              
                // Duplicate found, return false
                return false; 
            }
          
            // Insert the value into the current box's set
            subMat[idx].insert(val);
        }
    }
  
    // If no duplicates were found, return true
    return true;
}

int main() {

    vector<vector<int>> mat = {
        {9, 3, 0, 0, 7, 0, 0, 0, 0},
        {6, 0, 0, 1, 9, 5, 0, 0, 0},
        {0, 5, 8, 0, 0, 0, 0, 6, 0},
        {8, 0, 0, 0, 6, 0, 0, 0, 3},
        {4, 0, 0, 8, 0, 3, 0, 0, 1},
        {7, 0, 0, 0, 2, 0, 0, 0, 6},
        {0, 6, 0, 0, 0, 0, 2, 8, 0},
        {0, 0, 0, 4, 1, 9, 0, 0, 5},
        {0, 0, 0, 0, 8, 0, 0, 7, 9}
    };
    cout << (isValid(mat) ? "true" : "false") << "\n";
    return 0;
}

JAVA

import java.util.HashSet;

class GfG {

    // Function to check if the Sudoku matrix is valid
    static boolean isValid(int[][] mat) {

        // Arrays of sets to track seen numbers in rows,
        // columns, and subMatrices
        HashSet<Integer>[] rows = new HashSet[9];
        HashSet<Integer>[] cols = new HashSet[9];
        HashSet<Integer>[] subMat = new HashSet[9];

        // Initialize the sets
        for (int i = 0; i < 9; i++) {
            rows[i] = new HashSet<>();
            cols[i] = new HashSet<>();
            subMat[i] = new HashSet<>();
        }

        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                int val = mat[i][j];

                // Skip empty cells
                if (val == 0) continue;

                // Check for duplicates in the row
                if (rows[i].contains(val)) return false;
                rows[i].add(val);

                // Check for duplicates in the column
                if (cols[j].contains(val)) return false;
                cols[j].add(val);

                // Calculate the sub-matrix index
                int idx = (i / 3) * 3 + (j / 3);

                // Check for duplicates in the sub-matrix
                if (subMat[idx].contains(val)) return false;
                subMat[idx].add(val);
            }
        }
        return true;
    }

    public static void main(String[] args) {
        int[][] mat = {
            {9, 3, 0, 0, 7, 0, 0, 0, 0},
            {6, 0, 0, 1, 9, 5, 0, 0, 0},
            {0, 5, 8, 0, 0, 0, 0, 6, 0},
            {8, 0, 0, 0, 6, 0, 0, 0, 3},
            {4, 0, 0, 8, 0, 3, 0, 0, 1},
            {7, 0, 0, 0, 2, 0, 0, 0, 6},
            {0, 6, 0, 0, 0, 0, 2, 8, 0},
            {0, 0, 0, 4, 1, 9, 0, 0, 5},
            {0, 0, 0, 0, 8, 0, 0, 7, 9}
        };

        System.out.println(isValid(mat) ? "true" : "false");
    }
}

Python

# Function to check if the Sudoku matrix is valid
def isValid(mat):

    # Arrays of sets to track seen numbers in rows, cols
    rows = [set() for _ in range(9)]
    cols = [set() for _ in range(9)]
    subMat = [set() for _ in range(9)]

    # Loop through the Sudoku grid
    for i in range(9):
        for j in range(9):
            val = mat[i][j]

            # Skip empty cells
            if val == 0:
                continue

            # Check for duplicates in the row
            if val in rows[i]:
                return False
            rows[i].add(val)

            # Check for duplicates in the column
            if val in cols[j]:
                return False
            cols[j].add(val)

            # Calculate the sub-matrix index
            idx = (i // 3) * 3 + (j // 3)

            # Check for duplicates in the sub-matrix
            if val in subMat[idx]:
                return False
            subMat[idx].add(val)

    return True

# Example sudoku board
mat = [
    [9, 3, 0, 0, 7, 0, 0, 0, 0],
    [6, 0, 0, 1, 9, 5, 0, 0, 0],
    [0, 5, 8, 0, 0, 0, 0, 6, 0],
    [8, 0, 0, 0, 6, 0, 0, 0, 3],
    [4, 0, 0, 8, 0, 3, 0, 0, 1],
    [7, 0, 0, 0, 2, 0, 0, 0, 6],
    [0, 6, 0, 0, 0, 0, 2, 8, 0],
    [0, 0, 0, 4, 1, 9, 0, 0, 5],
    [0, 0, 0, 0, 8, 0, 0, 7, 9]
]

# Check if the Sudoku matrix is valid
print("true" if isValid(mat) else "false")

C#

using System;
using System.Collections.Generic;

class GfG {

    // Function to check if the Sudoku matrix is valid
    static bool IsValid(int[, ] mat)
    {

        // Arrays of sets to track seen numbers in rows,
        // cols
        HashSet<int>[] rows = new HashSet<int>[ 9 ];
        HashSet<int>[] cols = new HashSet<int>[ 9 ];
        HashSet<int>[] subMat = new HashSet<int>[ 9 ];

        // Initialize the sets
        for (int i = 0; i < 9; i++) {
            rows[i] = new HashSet<int>();
            cols[i] = new HashSet<int>();
            subMat[i] = new HashSet<int>();
        }

        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                int val = mat[i, j];

                // Skip empty cells
                if (val == 0)
                    continue;

                // Check for duplicates in the row
                if (rows[i].Contains(val))
                    return false;
                rows[i].Add(val);

                // Check for duplicates in the column
                if (cols[j].Contains(val))
                    return false;
                cols[j].Add(val);

                // Calculate the sub-matrix index
                int idx = (i / 3) * 3 + j / 3;

                // Check for duplicates in the sub-matrix
                if (subMat[idx].Contains(val))
                    return false;
                subMat[idx].Add(val);
            }
        }
        return true;
    }

    static void Main()
    {
        int[, ] mat = { { 9, 3, 0, 0, 7, 0, 0, 0, 0 },
                        { 6, 0, 0, 1, 9, 5, 0, 0, 0 },
                        { 0, 5, 8, 0, 0, 0, 0, 6, 0 },
                        { 8, 0, 0, 0, 6, 0, 0, 0, 3 },
                        { 4, 0, 0, 8, 0, 3, 0, 0, 1 },
                        { 7, 0, 0, 0, 2, 0, 0, 0, 6 },
                        { 0, 6, 0, 0, 0, 0, 2, 8, 0 },
                        { 0, 0, 0, 4, 1, 9, 0, 0, 5 },
                        { 0, 0, 0, 0, 8, 0, 0, 7, 9 } };

        Console.WriteLine(IsValid(mat) ? "true" : "false");
    }
}

JavaScript

// Function to check if the Sudoku matrix is valid
function isValid(mat){

    // Arrays to track seen numbers in rows, cols, and
    // subMatrices
    let rows = Array.from({length : 9}, () => new Set());
    let cols = Array.from({length : 9}, () => new Set());
    let subMat = Array.from({length : 9}, () => new Set());

    // Loop through the Sudoku grid
    for (let i = 0; i < 9; i++) {
        for (let j = 0; j < 9; j++) {
            let val = mat[i][j];

            // Skip empty cells
            if (val === 0)
                continue;

            // Check for duplicates in the row
            if (rows[i].has(val))
                return false;
            rows[i].add(val);

            // Check for duplicates in the column
            if (cols[j].has(val))
                return false;
            cols[j].add(val);

            // Calculate the sub-matrix index
            let idx
                = Math.floor(i / 3) * 3 + Math.floor(j / 3);

            // Check for duplicates in the sub-matrix
            if (subMat[idx].has(val))
                return false;
            subMat[idx].add(val);
        }
    }
    return true;
}

let mat = [
    [ 9, 3, 0, 0, 7, 0, 0, 0, 0 ],
    [ 6, 0, 0, 1, 9, 5, 0, 0, 0 ],
    [ 0, 5, 8, 0, 0, 0, 0, 6, 0 ],
    [ 8, 0, 0, 0, 6, 0, 0, 0, 3 ],
    [ 4, 0, 0, 8, 0, 3, 0, 0, 1 ],
    [ 7, 0, 0, 0, 2, 0, 0, 0, 6 ],
    [ 0, 6, 0, 0, 0, 0, 2, 8, 0 ],
    [ 0, 0, 0, 4, 1, 9, 0, 0, 5 ],
    [ 0, 0, 0, 0, 8, 0, 0, 7, 9 ]
];
console.log(isValid(mat) ? "true" : "false");

Time Complexity: O(n2), where each operation (findnig and inserting) on unordered set requires O(1) on average, iterating over all n x n cells causes O.
Auxiliary Space: O(n2) auxiliary space resulting from three arrays of n unordered sets one for rows, one for columns, and one for submatrices. Every set can save up to n elements, which results in O(n²) overall space use.