leetcode Sudoku Solver

本文介绍了一个用于解决Sudoku谜题的编程算法,包括验证规则、回溯搜索等关键步骤,确保唯一解的存在。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character '.'.

You may assume that there will be only one unique solution.

class Solution {
 public:
  typedef vector<vector<char> > VVC;
  char getIthCh(const VVC& board, int x, int y, int idx, int type) {
    if (type == 1)
      return board[x][idx];
    else if (type == 2)
      return board[idx][y];
    else if (type == 3) {
      int bx = x / 3 * 3, by = y / 3 * 3, vx = idx / 3, vy = idx % 3;
      return board[bx+vx][by+vy];
    }
    return NULL;
  }
  bool valid(const VVC& board, int x, int y) {
    int exist[9] = {0};
    for (int t = 1; t <= 3; ++t) {
      memset(exist, 0, sizeof(int)*9);
      for (int i = 0; i < 9; ++i) {
        char ch = getIthCh(board, x, y, i, t);
        if (ch != '.') {
          if (exist[ch-'1'])
            return false;
          else
            exist[ch-'1'] = 1;          
        }
      }
    }
    return true;
  }

  bool solve(vector<vector<char>>& board) {
    int i, j;
    for (i = 0; i < 9; ++i)
      for (j = 0; j < 9; ++j)
        if (board[i][j] == '.') {
          for (char ch = '1'; ch <= '9'; ++ch) {
            board[i][j] = ch;
            if (valid(board, i, j) && solve(board) )
              return true;
            board[i][j] = '.';
          }
          return false;
        }
    return true;
  }
  void solveSudoku(vector<vector<char> > &board) {
    // IMPORTANT: Please reset any member data you declared, as
    // the same Solution instance will be reused for each test case.
    solve(board);    
  }
};


A wrong code, find the bug:

 

 

class Solution {
 public:
  typedef vector<vector<char> > VVC;
  char getIthCh(const VVC& board, int x, int y, int idx, int type) {
    if (type == 1)
      return board[x][idx];
    else if (type == 2)
      return board[idx][y];
    else if (type == 3) {
      int bx = x / 3 * 3, by = y / 3 * 3, vx = idx / 3, vy = idx % 3;
      return board[bx+vx][by+vy];
    }
    return NULL;
  }
  bool valid(const VVC& board, int x, int y) {
    int exist[10] = {0};
    for (int t = 1; t <= 3; ++t) {
      for (int i = 0; i < 10; ++i) {
        char ch = getIthCh(board, x, y, i, t);
        if (exist[ch-'0'])
          return false;
      }
    }
    return true;
  }

  bool solve(vector<vector<char>>& board) {
    int i, j;
    for (i = 0; i < 9; ++i)
      for (j = 0; j < 9; ++j)
        if (board[i][j] == '.') {
          for (char ch = '1'; ch <= '9'; ++ch) {
            board[i][j] = ch;
            if (valid(board, i, j) && solve(board) )
              return true;
            board[i][j] = '.';
          }
          return false;
        }
    return true;
  }
  void solveSudoku(vector<vector<char> > &board) {
    // IMPORTANT: Please reset any member data you declared, as
    // the same Solution instance will be reused for each test case.
    solve(board);    
  }
};

 

 

 

 

 

 

It's not convenient to record the options for every node when backtrack, so a direct traverse is inevitable. The code is like:

 

 

class Solution {
 public:
  bool valid(vector<vector<char>>& board, int x, int y) {
    int i, j;
    int exist[9] = {0};
    for (i = 0; i < 9; ++i)
      if (board[x][i] != '.')
        if (exist[board[x][i] - '1'] == 0)
          exist[board[x][i] - '1'] = 1;
        else
          return false;
    memset(exist,0,sizeof(int) * 9);
    for (i = 0; i < 9; ++i)
      if (board[i][y] != '.')
        if (exist[board[i][y] - '1'] == 0)
          exist[board[i][y] - '1'] = 1;
        else
          return false;
    
    int x_offset = x / 3, y_offset = y / 3;
    memset(exist,0,sizeof(int) * 9);
    for (i = 0; i < 9; ++i) {
      char ch = board[i / 3 + x_offset * 3][i % 3 + y_offset * 3];
      if (ch != '.')
        if (exist[ch - '1'] == 0)
          exist[ch - '1'] = 1;
        else
          return false;
    }
    return true;      
  }
  bool solve(vector<vector<char>>& board) {
    int i, j;
    for (i = 0; i < 9; ++i)
      for (j = 0; j < 9; ++j)
        if (board[i][j] == '.') {
          for (char ch = '1'; ch <= '9'; ++ch) {
            board[i][j] = ch;
            if (valid(board, i, j) && solve(board) )
              return true;
            board[i][j] = '.';
          }
          return false;
        }
    return true;
  }
  void solveSudoku(vector<vector<char> > &board) {
    // IMPORTANT: Please reset any member data you declared, as
    // the same Solution instance will be reused for each test case.
    solve(board);    
  }
};

 

Read input from file, then write to file:

 

 

x 3 x x 2 x 4 x x
9 x x x 4 x 8 x x
8 x x x 3 7 x x 5
3 5 x x x 9 7 x 8
x x 8 4 x 3 1 x x
7 x 9 2 x x x 4 3
4 x x 8 1 x x x 7
x x 5 x 9 x x x 2
x x 7 x 5 x x 1 x

x x 7 3 5 x x 8 x
x x x x 6 8 x 3 4
x x x x x x 1 9 x
6 x x x x x 8 5 7
x x x 5 x 6 x x x
5 8 9 x x x x x 6
x 5 8 x x x x x x
9 6 x 7 3 x x x x
x 1 x x 4 2 5 x x

 

5 3 6 9 2 8 4 7 1
9 7 2 5 4 1 8 3 6
8 4 1 6 3 7 2 9 5
3 5 4 1 6 9 7 2 8
6 2 8 4 7 3 1 5 9
7 1 9 2 8 5 6 4 3
4 9 3 8 1 2 5 6 7
1 6 5 7 9 4 3 8 2
2 8 7 3 5 6 9 1 4

4 9 7 3 5 1 6 8 2
1 2 5 9 6 8 7 3 4
8 3 6 4 2 7 1 9 5
6 4 1 2 9 3 8 5 7
3 7 2 5 8 6 9 4 1
5 8 9 1 7 4 3 2 6
2 5 8 6 1 9 4 7 3
9 6 4 7 3 5 2 1 8
7 1 3 8 4 2 5 6 9

 

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
bool valid(vector<vector<char>>& board, int x, int y) {
  char exist[10] = {0};

  for (int i = 0; i < 9; ++i)
    if (board[x][i] != 'x')
      if (!exist[board[x][i]-'0'])
        exist[board[x][i]-'0'] = 1;
      else
        return false;
  
  memset(exist, 0, 10*sizeof(char));
  for (int i = 0; i < 9; ++i)
    if (board[i][y] != 'x')
      if (!exist[board[i][y]-'0'])
        exist[board[i][y]-'0'] = 1;
      else
        return false;

  memset(exist, 0, 10*sizeof(char));
  int offsetx = x / 3, offsety = y / 3;

  for (int i = 0; i < 3; ++i)
    for (int j = 0; j < 3; ++j)
      if (board[offsetx*3+i][offsety*3+j] != 'x') 
        if (!exist[board[offsetx*3+i][offsety*3+j]-'0'])
          exist[board[offsetx*3+i][offsety*3+j]-'0'] = 1;
        else 
          return false;      
  
  return true;
}
bool SolveSudoku(vector<vector<char>>& board) {
  for (int i = 0; i < 9; ++i)
    for (int j = 0; j < 9; ++j)
      if (board[i][j] == 'x') {
        for (char ch = '1'; ch <= '9'; ++ch) {
          board[i][j] = ch;
          if (valid(board, i, j) && SolveSudoku(board))
            return true;
          board[i][j] = 'x';
        }
        return false;
      }  
  return true;
}
int main(){

  if (freopen("E:\\resume\\Microsoft\\Step 1 Problem and Check\\Sudoku\\SampleInput.txt","r",stdin) == NULL)
    printf("open fail\n");
  if (freopen("E:\\resume\\Microsoft\\Step 1 Problem and Check\\SudokuOutput.txt","w",stdout) == NULL)
    printf("open fail\n");

  vector<vector<char> > board(9, vector<char>(9,'x'));
  int linenum = 0;
  char line[30];

  while (!feof(stdin)) {
    gets(line);
    if (line[0] == '\0') {
      linenum = 0;
      if(SolveSudoku(board)) {
        for (int i = 0; i < 9; ++i){
          for (int j = 0; j < 8; ++j)
            printf("%c ", board[i][j]);
          printf("%c\n", board[i][8]);
        }
      }
      printf("\n");
    }
    else {
      for (int i = 0; i <= 8; ++i)
        board[linenum][i] = line[i*2];
      ++linenum;
    }
  }

  if(SolveSudoku(board)) {
    for (int i = 0; i < 9; ++i){
      for (int j = 0; j < 8; ++j)
        printf("%c ", board[i][j]);
      printf("%c\n", board[i][8]);
    }
  }


	return 0;
}

Python Version:

import copy


class Solution:
    def IsValid(self, board, row, col, val, n):
        baseRow, baseCol = row // 3 * 3, col // 3 * 3

        for i in range(n):
            if (board[row][i] == val and i != col):
                return False
            if (board[i][col] == val and i != row):
                return False
            deltaRow, deltaCol = i // 3, i % 3
            if (board[baseRow + deltaRow][baseCol + deltaCol] == val):
                return False
        return True

    def Backtrack(self, board, pos, n, res):
        if (res):
            return
        if (pos == n * n):
            res.append(copy.deepcopy(board))
            return
        row = pos // n
        col = pos % n

        if (board[row][col] == '.'):
            for i in range(1, n + 1):
                if (self.IsValid(board, row, col, str(i), n)):
                    board[row][col] = str(i)
                    self.Backtrack(board, pos + 1, n, res)
            board[row][col] = '.'
        else:
            self.Backtrack(board, pos + 1, n, res)

    def solveSudoku2(self, board):
        res = []
        self.Backtrack(board, 0, 9, res)
        for i in range(9):
            for j in range(9):
                board[i][j] = res[0][i][j]

    def solveSudoku(self, board):
        pos = 0
        status = [1 for i in range(81)]
        for i in range(9):
            for j in range(9):
                if (board[i][j] != '.'):
                    status[i * 9 + j] = 0
        while (pos > -1):
            row, col = pos // 9, pos % 9
            if (pos == 81):
                return
            if (status[pos] > 0):  # The original num at pos is not num
                while (self.IsValid(board, row, col, str(status[pos]), 9) == False and status[pos] < 10):
                    status[pos] += 1
                if (status[pos] < 10):
                    board[row][col] = str(status[pos])
                    pos += 1
                else:
                    board[row][col] = '.'
                    status[pos] = 1
                    pos -= 1
                    while (status[pos] == 0 and pos > 0):
                        pos -= 1
            else:
                pos += 1

    def solveSudoku3(self, board):
        pos = 0
        status = [(lambda i : 0 if board[i//9][i%9] == '.' else -1)(i) for i in range(81)]
        while (pos > -1):
            row, col = pos // 9, pos % 9
            if (pos == 81):
                return
            elif (status[pos] < 0):
                pos += 1
            elif (status[pos] >= 0 and status[pos] < 9):
                status[pos] += 1
                if (self.IsValid(board, row, col, str(status[pos]), 9) == True):
                    board[row][col] = str(status[pos])
                    pos += 1
            elif (status[pos] == 9):
                board[row][col] = '.'
                status[pos] = 0
                pos -= 1
                while (status[pos] < 0 and pos > 0):
                    pos -= 1

if __name__ == '__main__':
    s = Solution()
    board = \
        [['.', '3', '.', '.', '2', '.', '4', '.', '.'],
         ['9', '.', '.', '.', '4', '.', '8', '.', '.'],
         ['8', '.', '.', '.', '3', '7', '.', '.', '5'],
         ['3', '5', '.', '.', '.', '9', '7', '.', '8'],
         ['.', '.', '8', '4', '.', '3', '1', '.', '.'],
         ['7', '.', '9', '2', '.', '.', '.', '4', '3'],
         ['4', '.', '.', '8', '1', '.', '.', '.', '7'],
         ['.', '.', '5', '.', '9', '.', '.', '.', '2'],
         ['.', '.', '7', '.', '5', '.', '.', '1', '.']];

    s.solveSudoku3(board)
    for row in board:
        print(row)

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值