演算法練習week4--leetcode37
題目描述
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules:
- Each of the digits
1-9
must occur exactly once in each row. - Each of the digits
1-9
must occur exactly once in each column. - Each of the the digits
1-9
must occur exactly once in each of the 93x3
sub-boxes of the grid.
Empty cells are indicated by the character '.'
.
A sudoku puzzle...
...and its solution numbers marked in red.
Note:
- The given board contain only digits
1-9
'.'
. - You may assume that the given Sudoku puzzle will have a single unique solution.
- The given board size is always
9x9
.
題目分析
首先這道題的思路的比較直觀,我們先把空著的格子統計出來放到一個ArrayList<int> 裡面, 然後開始運用dfs。每當填入一個數字的時候我們需要用isValid來驗證,只有不衝突的情況下才能新增進格子裡。
題意
解題思路:深度遍歷的過程,從開始一直掃描,直到遇到空字元,便可開始填數字,該位置的數字從1~9依次遍歷,不行的時候就回退。
演算法設計
1. checkValid方法中position是位置,位置從0開始,直到81時結束,根據position可以確定此時的行和列。該方法的含義是判斷在給position位置填寫了數之後,行列以及塊是否合法,即是否會出現相同的數字出現
2. solve方法是核心:從開始的位置一直掃描,直到遇到非數字,然後開始遞迴,.的位置有可能是任何數字,然後從1-9開始試,將該位置的值設為1-9中的其中一個之後,呼叫checkValid方法判斷該位置為填充上值之後是否合法,如果合法,繼續下一個位置的判斷,即開始遞迴。當該遞迴返回時,如果是false,則表示剛才的位置數字填錯了,需要重新填,則先恢復,在繼續試探。直到返回true為止,否則返回false
3 可以考慮“先放置,再判斷”的方案。
4 所有的方案(k從1到9)完畢之後,應該返回錯誤,這個是不應該被忽略的。
5 最後一點需要注意的是,當i,j迴圈完畢之後,實際上是最終/最底層的一次迴圈,表明已經解出了sudoku,返回ture.
演算法實現
class Solution
{
public:
bool isValid(vector<vector<char> > &board, int x, int y)
{
int i, j;
for (i = 0; i < 9; i++)
if (i != x && board[i][y] == board[x][y])
return false;
for (j = 0; j < 9; j++)
if (j != y && board[x][j] == board[x][y])
return false;
for (i = 3 * (x / 3); i < 3 * (x / 3 + 1); i++)
for (j = 3 * (y / 3); j < 3 * (y / 3 + 1); j++)
if (i != x && j != y && board[i][j] == board[x][y])
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])
{
for (int k = 1; k <= 9; ++k)
{
board[i][j] = '0' + k;
if (isValid(board, i, j) && solveSudoku(board))
return true;
board[i][j] = '.';
}
return false;
}
}
return true;
}
};
解題心得
DFS常常和貪心演算法一起使用,它適合資料和計算量不太大的情況,針對每種可能進行嘗試、判斷、計算,找出最優解即可。但是,當資料量較大時,DFS可能產生計算量極大的情況,這種情況會大大降低演算法效率,因此,要特別謹慎使用!