Vérification d'une grille Sudoku 9×9

Approche par marquage avec ensembles de bits

Une solution élégante consiste à utiliser trois tableaux de masques de bits pour suivre les présences respectivement dans les lignes, les colonnes et les sous-grilles. Cette technique évite les réinitialisations répétées et offre une complexité temporelle en O(1) avec un espace constant.

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& grille) {
        int ligne[9] = {0};
        int colonne[9] = {0};
        int bloc[9] = {0};
        
        for (int i = 0; i < 9; ++i) {
            for (int j = 0; j < 9; ++j) {
                if (grille[i][j] == '.') continue;
                
                int chiffre = grille[i][j] - '1';
                int masque = 1 << chiffre;
                int idxBloc = (i / 3) * 3 + (j / 3);
                
                if ((ligne[i] & masque) || 
                    (colonne[j] & masque) || 
                    (bloc[idxBloc] & masque)) {
                    return false;
                }
                
                ligne[i] |= masque;
                colonne[j] |= masque;
                bloc[idxBloc] |= masque;
            }
        }
        return true;
    }
};

Alternative avec table de hachage

Pour une approche plus explicite, on peut utiliser des ensembles pour chaque ligne, colonne et bloc :

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& grille) {
        unordered_set<int> vueLigne[9];
        unordered_set<int> vueColonne[9];
        unordered_set<int> vueRegion[9];
        
        for (int rang = 0; rang < 9; ++rang) {
            for (int colonne = 0; colonne < 9; ++colonne) {
                char symbole = grille[rang][colonne];
                if (symbole == '.') continue;
                
                int valeur = symbole - '0';
                int idRegion = (rang / 3) * 3 + colonne / 3;
                
                if (!vueLigne[rang].insert(valeur).second) return false;
                if (!vueColonne[colonne].insert(valeur).second) return false;
                if (!vueRegion[idRegion].insert(valeur).second) return false;
            }
        }
        return true;
    }
};

Version Python condensée

En Python, la vérification peut s'écrire de manière très compacte :

class Solution:
    def isValidSudoku(self, grille: list[list[str]]) -> bool:
        rangees = [set() for _ in range(9)]
        colonnes = [set() for _ in range(9)]
        carres = [set() for _ in range(9)]
        
        for i in range(9):
            for j in range(9):
                case = grille[i][j]
                if case == '.':
                    continue
                    
                if case in rangees[i]:
                    return False
                rangees[i].add(case)
                
                if case in colonnes[j]:
                    return False
                colonnes[j].add(case)
                
                id_carre = (i // 3) * 3 + j // 3
                if case in carres[id_carre]:
                    return False
                carres[id_carre].add(case)
                
        return True

La clé pour identifier le bloc 3×3 d'une cellule située aux coordonnées (i, j) réside dans la formule (i // 3) * 3 + j // 3, qui projette les indices sur une grille 3×3 de régions.

Étiquettes: leetcode algorithm Sudoku bit-manipulation hash-set

Publié le 13 août à 12h03