Sudoku Solver

2014.2.28 21:30

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.

A sudoku puzzle...

...and its solution numbers marked in red.

Solution:

  My solution to this problem is by DFS and backtracking. The difference is that I added some optimization strategies to the program:

    1. [7][6] can be represented as [7 * 9 + 6], you don't have to calculate it every time, store the coordinates in an array instead.

    2. [69] can be represented as [69 / 9][69 % 9], you don't have to calculate it every time, becasue '/' and '%' are expensive operators.

    3. When you've filled in a blank, where is the next blank to fill? You can find the next blank in O(1) time, instead of scanning the whole board.

    4. When one attempt failed, how do you backtrack efficiently? With a <vector>, pop_back() and push_back() is a good choice.

  The Dancing Links Algorithm seems to be a very exquisite way to solve Sudoku, but here it might be way too complicated for an interview question. Perhaps I'm just too lazy to learn it, spare me~(>_<)

  Total time complexity is O((n^2)!), but it would never appear that large. Space complexity is O(n^2).

Accepted code:

  1 // 1AC, very well, avoiding too much '/' and '%' will speed up the program.
  2 #include <cmath>
  3 #include <vector>
  4 using namespace std;
  5 
  6 class Solution {
  7 public:
  8     void solveSudoku(vector<vector<char> > &board) {
  9         n2 = (int)board.size();
 10         if (n2 == 0) {
 11             return;
 12         } else if (n2 == 1) {
 13             board[0][0] = '1';
 14             return;
 15         }
 16         
 17         n = (int)sqrt(1.0 * n2);
 18         n4 = n2 * n2;
 19         
 20         int i, j;
 21         row.resize(n2);
 22         for (i = 0; i < n2; ++i) {
 23             row[i].resize(n2);
 24         }
 25         col.resize(n2);
 26         for (i = 0; i < n2; ++i) {
 27             col[i].resize(n2);
 28         }
 29         block.resize(n2);
 30         for (i = 0; i < n2; ++i) {
 31             block[i].resize(n2);
 32         }
 33         bc.resize(n2);
 34         for (i = 0; i < n2; ++i) {
 35             bc[i].resize(n2);
 36         }
 37         row_coordinate.resize(n4);
 38         col_coordinate.resize(n4);
 39         for (i = 0; i < n4; ++i) {
 40             row_coordinate[i] = i / n2;
 41             col_coordinate[i] = i % n2;
 42         }
 43         
 44         for (i = 0; i < n2; ++i) {
 45             for (j = 0; j < n2; ++j) {
 46                 row[i][j] = col[i][j] = block[i][j] = 0;
 47             }
 48         }
 49         
 50         for (i = 0; i < n2; ++i) {
 51             for (j = 0; j < n2; ++j) {
 52                 bc[i][j] = i / n * n + j / n;
 53             }
 54         }
 55         
 56         cc = 0;
 57         for (i = 0; i < n2; ++i) {
 58             for (j = 0; j < n2; ++j) {
 59                 if (board[i][j] != '.') {
 60                     // it is a digit
 61                     row[i][board[i][j] - '1'] = 1;
 62                     col[j][board[i][j] - '1'] = 1;
 63                     block[bc[i][j]][board[i][j] - '1'] = 1;
 64                 } else {
 65                     empty_slots.push_back(i * n2 + j);
 66                     ++cc;
 67                 }
 68             }
 69         }
 70         
 71         suc = false;
 72         dfs(board);
 73         
 74         // perform cleanup operations
 75         for (i = 0; i < n2; ++i) {
 76             row[i].clear();
 77             col[i].clear();
 78             block[i].clear();
 79             bc[i].clear();
 80         }
 81         row.clear();
 82         col.clear();
 83         block.clear();
 84         bc.clear();
 85         empty_slots.clear();
 86         row_coordinate.clear();
 87         col_coordinate.clear();
 88     }
 89 private:
 90     bool suc;
 91     int n, n2, n4;
 92     int cc;
 93     vector<vector<int> > row, col, block;
 94     vector<vector<int> > bc;
 95     vector<int> empty_slots;
 96     vector<int> row_coordinate, col_coordinate;
 97     
 98     void dfs(vector<vector<char> > &board) {
 99         if (suc) {
100             return;
101         }
102         if (cc == 0) {
103             suc = true;
104             return;
105         }
106 
107         int r, c;
108         int i;
109 
110         r = row_coordinate[empty_slots[cc - 1]];
111         c = col_coordinate[empty_slots[cc - 1]];
112         for (i = 0; i < n2; ++i) {
113             if (row[r][i] || col[c][i] || block[bc[r][c]][i]) {
114                 continue;
115             }
116             row[r][i] = 1;
117             col[c][i] = 1;
118             block[bc[r][c]][i] = 1;
119             empty_slots.pop_back();
120             --cc;
121             board[r][c] = (i + '1');
122             
123             dfs(board);
124             if (suc) {
125                 return;
126             }
127             
128             row[r][i] = 0;
129             col[c][i] = 0;
130             block[bc[r][c]][i] = 0;
131             empty_slots.push_back(r * n2 + c);
132             ++cc;
133             board[r][c] = '.';
134         }
135     }
136 };

 

 posted on 2014-02-28 21:54  zhuli19901106  阅读(465)  评论(0编辑  收藏  举报