Lesson 8 of 250
36. Valid Sudoku
NeetCode: Valid Sudoku · LeetCode: 36. Valid Sudoku · Difficulty: Medium
Determine whether a partially filled 9x9 board is valid. Each row, each column, and each of the nine 3x3 boxes may contain the digits 1-9 at most once. Empty cells are .. The board need not be solvable.
Example
A board with two 5s in the same row -> false
A board with no repeated digit in any row, column, or box -> trueBrute force: check each unit separately
Make three passes: one over every row, one over every column, one over every 3x3 box. Each check collects the digits of that unit in a HashSet<Character> and fails on a repeat: Set.add returns false when the element is already present. The board is a char[][], and main builds it from row strings with a small parse helper.
import java.util.HashSet;
import java.util.Set;
public class Main {
static class Solution {
public boolean isValidSudoku(char[][] board) {
for (int r = 0; r < 9; r++) {
Set<Character> seen = new HashSet<>();
for (int c = 0; c < 9; c++) {
if (!fresh(seen, board[r][c])) return false;
}
}
for (int c = 0; c < 9; c++) {
Set<Character> seen = new HashSet<>();
for (int r = 0; r < 9; r++) {
if (!fresh(seen, board[r][c])) return false;
}
}
for (int boxR = 0; boxR < 3; boxR++) {
for (int boxC = 0; boxC < 3; boxC++) {
Set<Character> seen = new HashSet<>();
for (int i = 0; i < 9; i++) {
if (!fresh(seen, board[boxR * 3 + i / 3][boxC * 3 + i % 3])) return false;
}
}
}
return true;
}
// False when the digit was already in the set. Empty cells are ignored.
private boolean fresh(Set<Character> seen, char ch) {
return ch == '.' || seen.add(ch);
}
}
public static void main(String[] args) {
Solution sol = new Solution();
char[][] good = parse(
"53..7....", "6..195...", ".98....6.", "8...6...3", "4..8.3..1",
"7...2...6", ".6....28.", "...419..5", "....8..79");
char[][] bad = parse(
"53..7....", "6..195...", ".98....6.", "8...6...3", "4..8.3..1",
"7...2...6", ".6....28.", "...419..5", "....8..75");
System.out.println(sol.isValidSudoku(good));
System.out.println(sol.isValidSudoku(bad));
}
// Builds the char[][] board from nine row strings.
static char[][] parse(String... rows) {
char[][] board = new char[rows.length][];
for (int i = 0; i < rows.length; i++) {
board[i] = rows[i].toCharArray();
}
return board;
}
}true
falseTime: O(81), which is constant for a fixed board size. Space: O(9).
Optimal: one pass with bitmasks
Visit each cell once. Keep 9 integers for rows, 9 for columns, and 9 for boxes, where bit d of an int records that digit d has appeared. 1 << (ch - '1') turns the character '1' to '9' into a bit from 0 to 8. A cell's box number is (r / 3) * 3 + c / 3. If the digit's bit is already set in its row, column, or box, the board is invalid.
public class Main {
static class Solution {
public boolean isValidSudoku(char[][] board) {
int[] rows = new int[9];
int[] cols = new int[9];
int[] boxes = new int[9];
for (int r = 0; r < 9; r++) {
for (int c = 0; c < 9; c++) {
char ch = board[r][c];
if (ch == '.') {
continue;
}
int bit = 1 << (ch - '1');
int b = (r / 3) * 3 + c / 3;
if ((rows[r] & bit) != 0 || (cols[c] & bit) != 0 || (boxes[b] & bit) != 0) {
return false;
}
rows[r] |= bit;
cols[c] |= bit;
boxes[b] |= bit;
}
}
return true;
}
}
public static void main(String[] args) {
Solution sol = new Solution();
char[][] good = parse(
"53..7....", "6..195...", ".98....6.", "8...6...3", "4..8.3..1",
"7...2...6", ".6....28.", "...419..5", "....8..79");
char[][] bad = parse(
"53..7....", "6..195...", ".98....6.", "8...6...3", "4..8.3..1",
"7...2...6", ".6....28.", "...419..5", "....8..75");
System.out.println(sol.isValidSudoku(good));
System.out.println(sol.isValidSudoku(bad));
}
// Builds the char[][] board from nine row strings.
static char[][] parse(String... rows) {
char[][] board = new char[rows.length][];
for (int i = 0; i < rows.length; i++) {
board[i] = rows[i].toCharArray();
}
return board;
}
}true
falseTime: O(81), a single pass. Space: O(1): 27 int values.
Both versions are constant time for a 9x9 board; the single pass does a third of the work and generalizes to n x n boards.
