Open In App

Check Sudoku solution is valid or not

Last Updated : 07 Oct, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a solution of Sudoku puzzle, the task is to check whether the given sudoku solution is valid or not. A valid solution requires that each row, column, and 3×3 sub-matrix must contain the digits 1-9 without repetition.

Examples:

Input:

sudoku-solution-example

Output: true
Explanation: This sudoku solution is valid.

In our previous article, we discussed how to check whether a Sudoku board configuration is valid. And for this problem, the approach remains the same. However, while that article focused on validating configurations, here we will be validating a complete Sudoku solution.

Using Array of Fixed Length

To check whether a given sudoku solution is valid or not. We have to make sure that each number (1-9) appears only once per row, column, and 3×3 sub-matrix. We can use array or hash table for keeping track of seen/visited elements, Here we have used auxiliary arrays to track the seen/visited of each number in rows, columns, and sub-matrix.

Step-by-step approach:

  • We use three 2D arrays (rows, cols, subMat) to track which numbers have already appeared in each row, column, and sub-matrix, respectively.
  • For each cell, we skip if it contains 0 (empty). Otherwise, we check if the number has already appeared in the corresponding row, column, or sub-matrix. If so, the matrix is invalid.
  • The sub-matrix index is calculated as (i / 3) * 3 + j / 3 where i and j are the row and column indices.
  • If the current number is not visited before in the current row, column, or sub-matrix then marked as seen/visited.
C++
#include <bits/stdc++.h>
using namespace std;

// Function to check if the Sudoku matrix is valid
int isValid(vector<vector<int>> mat){
  
    // Track of numbers in rows, columns, and sub-matrix
    vector<vector<int>> rows(10, vector<int>(10, 0));
    vector<vector<int>> cols(10, vector<int>(10, 0));
    vector<vector<int>> subMat(10, vector<int>(10, 0));

    for (int i = 0; i < 9; i++){
        for (int j = 0; j < 9; j++){

            // Skip empty cells
            if (mat[i][j] == 0)
                continue;

            // Current value
            int val = mat[i][j]; 

            // Check for duplicates in row
            if (rows[i][val] == 1)
                return false;

            // Mark as seen
            rows[i][val] = 1; 

            // Check for duplicates in column
            if (cols[j][val] == 1)
                return false;

            // Mark as seen
            cols[j][val] = 1; 

            // Check for duplicates in sub-grid
            int idx = (i / 3) * 3 + j / 3;
            if (subMat[idx][val] == 1)
                return false;

            // Mark as seen
            subMat[idx][val] = 1; 
        }
    }

    return true;
}

int main(){
    vector<vector<int>> mat = 
                     {{7, 9, 2, 1, 5, 4, 3, 8, 6}, 
                     {6, 4, 3, 8, 2, 7, 1, 5, 9},
                     {8, 5, 1, 3, 9, 6, 7, 2, 4},
                     {2, 6, 5, 9, 7, 3, 8, 4, 1},
                     {4, 8, 9, 5, 6, 1, 2, 7, 3},
                     {3, 1, 7, 4, 8, 2, 9, 6, 5},
                     {1, 3, 6, 7, 4, 8, 5, 9, 2},
                     {9, 7, 4, 2, 1, 5, 6, 3, 8},
                     {5, 2, 8, 6, 3, 9, 4, 1, 7}};

    cout << (isValid(mat) ? "true" : "false") << "\n";

    return 0;
}
C
#include <stdio.h>
#include <stdbool.h>

int isValid(int mat[9][9]) {
  
    // Track of numbers in rows, columns, and sub-matrix
    int rows[10][10] = {0};
    int cols[10][10] = {0};
    int subMat[10][10] = {0};

    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
          
            // Skip empty cells
            if (mat[i][j] == 0)
                continue;

            // Current value
            int val = mat[i][j];

            // Check for duplicates in row
            if (rows[i][val] == 1)
                return false; // false

            // Mark as seen
            rows[i][val] = 1;

            // Check for duplicates in column
            if (cols[j][val] == 1)
                return false; // false

            // Mark as seen
            cols[j][val] = 1;

            // Check for duplicates in sub-grid
            int idx = (i / 3) * 3 + j / 3;
            if (subMat[idx][val] == 1)
                return 0; 

            // Mark as seen
            subMat[idx][val] = 1;
        }
    }

    return true;
}

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

    printf("%s\n", isValid(mat) ? "true" : "false");

    return 0;
}
Java
class GfG {
    static boolean isValid(int[][] mat) {
      
        // Track of numbers in rows, columns, and sub-matrix
        int[][] rows = new int[10][10];
        int[][] cols = new int[10][10];
        int[][] subMat = new int[10][10];

        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
              
                // Skip empty cells
                if (mat[i][j] == 0) continue;

                // Current value
                int val = mat[i][j];

                // Check for duplicates in row
                if (rows[i][val] == 1) return false;

                // Mark as seen
                rows[i][val] = 1;

                // Check for duplicates in column
                if (cols[j][val] == 1) return false;

                // Mark as seen
                cols[j][val] = 1;

                // Check for duplicates in sub-grid
                int idx = (i / 3) * 3 + j / 3;
                if (subMat[idx][val] == 1) return false;

                // Mark as seen
                subMat[idx][val] = 1;
            }
        }
        return true;
    }

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

        System.out.println(isValid(mat) ? "true" : "false");
    }
}
Python
def isValid(mat):
  
    # Track of numbers in rows, columns, and sub-matrix
    rows = [[0] * 10 for _ in range(10)]
    cols = [[0] * 10 for _ in range(10)]
    subMat = [[0] * 10 for _ in range(10)]

    for i in range(9):
        for j in range(9):
            # Skip empty cells
            if mat[i][j] == 0:
                continue

            # Current value
            val = mat[i][j]

            # Check for duplicates in row
            if rows[i][val] == 1:
                return False

            # Mark as seen
            rows[i][val] = 1

            # Check for duplicates in column
            if cols[j][val] == 1:
                return False

            # Mark as seen
            cols[j][val] = 1

            # Check for duplicates in sub-grid
            idx = (i // 3) * 3 + j // 3
            if subMat[idx][val] == 1:
                return False

            # Mark as seen
            subMat[idx][val] = 1

    return True

mat = [[7, 9, 2, 1, 5, 4, 3, 8, 6],
      [6, 4, 3, 8, 2, 7, 1, 5, 9],
      [8, 5, 1, 3, 9, 6, 7, 2, 4],
      [2, 6, 5, 9, 7, 3, 8, 4, 1],
      [4, 8, 9, 5, 6, 1, 2, 7, 3],
      [3, 1, 7, 4, 8, 2, 9, 6, 5],
      [1, 3, 6, 7, 4, 8, 5, 9, 2],
      [9, 7, 4, 2, 1, 5, 6, 3, 8],
      [5, 2, 8, 6, 3, 9, 4, 1, 7]];

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)
    {
        // Track of numbers in rows, columns, and sub-matrix
        int[,] rows = new int[9, 10];
        int[,] cols = new int[9, 10];
        int[,] subMat = new int[9, 10];

        for (int i = 0; i < 9; i++)
        {
            for (int j = 0; j < 9; j++)
            {
                // Skip empty cells
                if (mat[i, j] == 0)
                    continue;

                // Current value
                int val = mat[i, j];

                // Check for duplicates in row
                if (rows[i, val] == 1)
                    return false;

                // Mark as seen
                rows[i, val] = 1;

                // Check for duplicates in column
                if (cols[j, val] == 1)
                    return false;

                // Mark as seen
                cols[j, val] = 1;

                // Check for duplicates in sub-grid
                int idx = (i / 3) * 3 + j / 3;
                if (subMat[idx, val] == 1)
                    return false;

                // Mark as seen
                subMat[idx, val] = 1;
            }
        }

        return true;
    }

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

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

Output
true

Time Complexity: O(n^2), where n is the size of the Sudoku matrix (i.e, 9). This is because we iterate through all n*n cells of the matrix.
Auxiliary Space: O(n^2), due to the three 2D arrays (rows, cols, subMat) of size n*n

Using Bitmasking

In the previous approach, we used arrays to track which numbers have appeared in each row, column, and sub-matrix. Now, we can make this more efficient by using bit manipulation, we represent the presence of numbers with bits in an integer, which reduces memory usage and improves time complexity as well. The implementation steps remain the same as above approach, apart from checking and marking visited values in row, column and sub-matrix.

Step-by-step approach:

  • Use a single integer for each row, column, and sub-matrix. Each bit in the integer corresponds to a number.
  • For each cell, we can use bitwise AND (&) to check if a number’s bit is already set. If it is, that means the number has appeared before and the Sudoku is invalid.
  • If the current cell value (i,e, mat[i][j]) is not set in the row, column, or sub-matrix then we have to set the bit for the number using bitwise OR operation (|=) to mark it visited.
C++
#include <bits/stdc++.h>
using namespace std;

bool isValid(vector<vector<int>> &mat) {

    // Arrays to track seen numbers in rows,
    // columns, and sub-matrix
    vector<int> rows(9);
    vector<int> cols(9);
    vector<int> subMat(9);

    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {

            // Skip empty cells
            if (mat[i][j] == 0)
                continue;

            int val = mat[i][j];

            // Bit position for the current value
            int pos = 1 << (val - 1); 

            // Check for duplicates in the current row
            if ((rows[i] & pos) > 0)
                return false;

            // Mark the value as seen in the row
            rows[i] |= pos; 

            // Check for duplicates in the current column
            if ((cols[j] & pos) > 0)
                return false; 

            // Mark the value as seen in the column
            cols[j] |= pos; 

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

            // Check for duplicates in the current sub-matrix
            if ((subMat[idx] & pos) > 0)
                return false;

            // Mark the value as seen in the sub-matrix
            subMat[idx] |= pos; 
        }
    }
    return true; 
}

int main(){
    vector<vector<int>> mat =
                    {{7, 9, 2, 1, 5, 4, 3, 8, 6}, 
                     {6, 4, 3, 8, 2, 7, 1, 5, 9},
                     {8, 5, 1, 3, 9, 6, 7, 2, 4},
                     {2, 6, 5, 9, 7, 3, 8, 4, 1},
                     {4, 8, 9, 5, 6, 1, 2, 7, 3},
                     {3, 1, 7, 4, 8, 2, 9, 6, 5},
                     {1, 3, 6, 7, 4, 8, 5, 9, 2},
                     {9, 7, 4, 2, 1, 5, 6, 3, 8},
                     {5, 2, 8, 6, 3, 9, 4, 1, 7}};

    cout << (isValid(mat) ? "true" : "false") << "\n";

    return 0;
}
C
#include <stdio.h>
#include <stdbool.h>

bool isValid(int mat[][9]) {
  
    // Arrays to track seen numbers in rows,
    // columns, and sub-matrix
    int rows[9] = {0}, cols[9] = {0}, subMat[9] = {0};

    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
          
            // Skip empty cells
            if (mat[i][j] == 0)
                continue;

            int val = mat[i][j];
            int pos = 1 << (val - 1);

            // Check for duplicates in the current row
            if ((rows[i] & pos) > 0)
                return false;
            rows[i] |= pos;

            // Check for duplicates in the current column
            if ((cols[j] & pos) > 0)
                return false;
            cols[j] |= pos;

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

            // Check for duplicates in the current sub-matrix
            if ((subMat[idx] & pos) > 0)
                return false;
            subMat[idx] |= pos;
        }
    }
    return true;
}

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

    printf("%s\n", isValid(mat) ? "true" : "false");
    return 0;
}
Java
import java.util.Arrays;

class GfG {
    static boolean isValid(int[][] mat) {
      
        // Arrays to track seen numbers in rows,
        // columns, and sub-matrix
        int[] rows = new int[9];
        int[] cols = new int[9];
        int[] subMat = new int[9];

        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
              
                // Skip empty cells
                if (mat[i][j] == 0)
                    continue;

                int val = mat[i][j];
                int pos = 1 << (val - 1);

                // Check for duplicates in the current row
                if ((rows[i] & pos) > 0)
                    return false;
                rows[i] |= pos;

                // Check for duplicates in the current column
                if ((cols[j] & pos) > 0)
                    return false;
                cols[j] |= pos;

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

                // Check for duplicates in the current sub-matrix
                if ((subMat[idx] & pos) > 0)
                    return false;
                subMat[idx] |= pos;
            }
        }
        return true;
    }

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

        System.out.println(isValid(mat) ? "true" : "false");
    }
}
Python
def isValid(mat):
  
    # Arrays to track seen numbers in rows,
    # columns, and sub-matrix
    rows = [0] * 9
    cols = [0] * 9
    subMat = [0] * 9

    for i in range(9):
        for j in range(9):
            # Skip empty cells
            if mat[i][j] == 0:
                continue

            val = mat[i][j]
            pos = 1 << (val - 1)

            # Check for duplicates in the current row
            if (rows[i] & pos) > 0:
                return False
            rows[i] |= pos

            # Check for duplicates in the current column
            if (cols[j] & pos) > 0:
                return False
            cols[j] |= pos

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

            # Check for duplicates in the current sub-matrix
            if (subMat[idx] & pos) > 0:
                return False
            subMat[idx] |= pos

    return True

if __name__ == "__main__":
    mat = [[7, 9, 2, 1, 5, 4, 3, 8, 6], 
          [6, 4, 3, 8, 2, 7, 1, 5, 9],
          [8, 5, 1, 3, 9, 6, 7, 2, 4],
          [2, 6, 5, 9, 7, 3, 8, 4, 1],
          [4, 8, 9, 5, 6, 1, 2, 7, 3],
          [3, 1, 7, 4, 8, 2, 9, 6, 5],
          [1, 3, 6, 7, 4, 8, 5, 9, 2],
          [9, 7, 4, 2, 1, 5, 6, 3, 8],
          [5, 2, 8, 6, 3, 9, 4, 1, 7]];

    print("true" if isValid(mat) else "false")
C#
using System;

class GfG {
    static bool IsValid(int[, ] mat){
        // Arrays to track seen numbers in rows, columns,
        // and sub-matrix
        int[] rows = new int[9];
        int[] cols = new int[9];
        int[] subMat = new int[9];

        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                // Skip empty cells
                if (mat[i, j] == 0)
                    continue;

                int val = mat[i, j];

                // Bit position for the current value
                int pos = 1 << (val - 1);

                // Check for duplicates in the current row
                if ((rows[i] & pos) > 0)
                    return false;

                // Mark the value as seen in the row
                rows[i] |= pos;

                // Check for duplicates in the current
                // column
                if ((cols[j] & pos) > 0)
                    return false;

                // Mark the value as seen in the column
                cols[j] |= pos;

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

                // Check for duplicates in the current
                // sub-matrix
                if ((subMat[idx] & pos) > 0)
                    return false;

                // Mark the value as seen in the sub-matrix
                subMat[idx] |= pos;
            }
        }
        return true;
    }

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

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

Output
true

Time Complexity: O(n^2), where n is the size of the Sudoku matrix (i.e, 9). This is because we iterate through all n*n cells of the matrix.
Auxiliary Space: O(n), as we use three arrays (rows, cols, subMat), each of size n to track the seen numbers for rows, columns, and sub-matrix. Each array element holds an integer, which is used for bitwise operations.

For more details and explanations about the solutions, please refer to our previous article.



Next Article

Similar Reads