36. Valid Sudoku - Leetcode Solution


đź’ˇ Step-by-Step Thought Process

  1. Understand the problem: Determine if a 9x9 Sudoku board is valid, where each row, column, and 3x3 sub-box must contain digits 1-9 without repetition, ignoring empty cells ('.').
  2. Validate rows: Iterate through each row i from 0 to 8, using a set to track seen digits. For each cell (i, j), if the cell is not '.' and the digit is already in the set, return False; otherwise, add the digit to the set.
  3. Validate columns: Iterate through each column j from 0 to 8, using a new set. For each cell (i, j), if the cell is not '.' and the digit is in the set, return False; otherwise, add the digit to the set.
  4. Validate 3x3 sub-boxes: Define starting coordinates for the nine 3x3 sub-boxes (e.g., (0,0), (0,3), (0,6), etc.). For each sub-box, use a set to track digits. Iterate through the 3x3 cells; if a digit is not '.' and is in the set, return False; otherwise, add it to the set.
  5. If all checks pass, return True, indicating the Sudoku board is valid.

Code Solution

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        # Validate Rows
        for i in range(9):
            s = set()
            for j in range(9):
                item = board[i][j]
                if item in s:
                    return False
                elif item != '.':
                    s.add(item)
        
        # Validate Cols
        for i in range(9):
            s = set()
            for j in range(9):
                item = board[j][i]
                if item in s:
                    return False
                elif item != '.':
                    s.add(item)
            
        # Validate Boxes
        starts = [(0, 0), (0, 3), (0, 6),
                  (3, 0), (3, 3), (3, 6),
                  (6, 0), (6, 3), (6, 6)]
        
        for i, j in starts:
            s = set()
            for row in range(i, i+3):
                for col in range(j, j+3):
                    item = board[row][col]
                    if item in s:
                        return False
                    elif item != '.':
                        s.add(item)
        return True

# Time Complexity: O(n^2)
# Space Complexity: O(n)
#include <vector>
#include <unordered_set>
using namespace std;

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        // Validate Rows
        for (int i = 0; i < 9; i++) {
            unordered_set<char> set;
            for (int j = 0; j < 9; j++) {
                char item = board[i][j];
                if (item != '.' && !set.insert(item).second) {
                    return false;
                }
            }
        }

        // Validate Columns
        for (int i = 0; i < 9; i++) {
            unordered_set<char> set;
            for (int j = 0; j < 9; j++) {
                char item = board[j][i];
                if (item != '.' && !set.insert(item).second) {
                    return false;
                }
            }
        }

        // Validate 3x3 Sub-grids
        vector<vector<int>> starts = {{0, 0}, {0, 3}, {0, 6},
                                      {3, 0}, {3, 3}, {3, 6},
                                      {6, 0}, {6, 3}, {6, 6}};
        
        for (auto& start : starts) {
            unordered_set<char> set;
            for (int row = start[0]; row < start[0] + 3; row++) {
                for (int col = start[1]; col < start[1] + 3; col++) {
                    char item = board[row][col];
                    if (item != '.' && !set.insert(item).second) {
                        return false;
                    }
                }
            }
        }

        return true;
    }
};
import java.util.HashSet;
import java.util.Set;

public class Solution {
    public boolean isValidSudoku(char[][] board) {
        // Validate Rows
        for (int i = 0; i < 9; i++) {
            Set<Character> set = new HashSet<>();
            for (int j = 0; j < 9; j++) {
                char item = board[i][j];
                if (item != '.' && !set.add(item)) {
                    return false;
                }
            }
        }

        // Validate Columns
        for (int i = 0; i < 9; i++) {
            Set<Character> set = new HashSet<>();
            for (int j = 0; j < 9; j++) {
                char item = board[j][i];
                if (item != '.' && !set.add(item)) {
                    return false;
                }
            }
        }

        // Validate 3x3 Sub-grids
        int[][] starts = {{0, 0}, {0, 3}, {0, 6},
                          {3, 0}, {3, 3}, {3, 6},
                          {6, 0}, {6, 3}, {6, 6}};
        
        for (int[] start : starts) {
            Set<Character> set = new HashSet<>();
            for (int row = start[0]; row < start[0] + 3; row++) {
                for (int col = start[1]; col < start[1] + 3; col++) {
                    char item = board[row][col];
                    if (item != '.' && !set.add(item)) {
                        return false;
                    }
                }
            }
        }

        return true;
    }
}
var isValidSudoku = function(board) {
    // Validate Rows
    for (let i = 0; i < 9; i++) {
        let set = new Set();
        for (let j = 0; j < 9; j++) {
            let item = board[i][j];
            if (item !== '.' && set.has(item)) {
                return false;
            }
            set.add(item);
        }
    }

    // Validate Columns
    for (let i = 0; i < 9; i++) {
        let set = new Set();
        for (let j = 0; j < 9; j++) {
            let item = board[j][i];
            if (item !== '.' && set.has(item)) {
                return false;
            }
            set.add(item);
        }
    }

    // Validate 3x3 Sub-grids
    let starts = [[0, 0], [0, 3], [0, 6],
                  [3, 0], [3, 3], [3, 6],
                  [6, 0], [6, 3], [6, 6]];
    
    for (let [startRow, startCol] of starts) {
        let set = new Set();
        for (let row = startRow; row < startRow + 3; row++) {
            for (let col = startCol; col < startCol + 3; col++) {
                let item = board[row][col];
                if (item !== '.' && set.has(item)) {
                    return false;
                }
                set.add(item);
            }
        }
    }

    return true;
};

Detailed Explanation

Understanding the Problem: Valid Sudoku

The “Valid Sudoku” problem asks us to determine whether a partially filled 9×9 Sudoku board is valid. A board is valid if:

  • Each row contains the digits 1–9 with no duplicates
  • Each column contains the digits 1–9 with no duplicates
  • Each of the nine 3Ă—3 sub-boxes contains the digits 1–9 with no duplicates

Empty cells are represented by the character '.' and should be ignored during validation.

Why This Problem Matters

Validating a Sudoku board is a useful exercise in applying set logic, matrix traversal, and multi-dimensional constraints. It frequently appears in coding interviews because it combines pattern checking with efficient scanning of 2D structures.

Brute Force Approach: Rule-by-Rule Validation

The problem can be broken down into three separate validations:

  1. Check each row: Iterate across each row using a set to track seen digits. If a digit reappears, return false.
  2. Check each column: For every column index, scan from top to bottom. Use a set to detect duplicate digits.
  3. Check each 3x3 sub-box: There are 9 sub-boxes starting at positions (0,0), (0,3), (0,6), (3,0), (3,3), etc. For each sub-box:
    • Use a set to track seen digits
    • Iterate through the 3 rows and 3 columns within the sub-box
    • If a digit is already in the set, return false

If no violations are found in any row, column, or sub-box, the board is valid.

Example Walkthrough

Here's a sample valid board layout:

[
  ["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"]
]

Each row, column, and 3Ă—3 box in this board has no duplicates (ignoring '.'), so it is valid.

Time and Space Complexity

Time Complexity: O(1) – The board is always 9×9, so we iterate over a constant number of cells.
Space Complexity: O(1) – We use fixed-size sets for rows, columns, and boxes, each handling at most 9 digits.

Edge Cases to Consider

  • An entirely empty board → valid
  • A full board with valid entries → valid
  • A board with duplicate digits in any row, column, or box → invalid
  • A board with non-digit, non-dot characters → assume invalid unless input constraints guarantee otherwise

Conclusion

The “Valid Sudoku” problem teaches how to apply multiple constraints across different dimensions of a matrix. By using simple data structures like sets and scanning in a structured way, you can implement an elegant and efficient solution that checks all rules without overcomplication.

NEW!Need help landing software roles? đź’ˇ