在这个great book中,我们被要求设计一种算法,以确定某人是否在一个井字游戏中获胜。 给出了以下解决方案,之后作者说:
注意,运行时可以通过添加来减少到O(N) 行和列计数数组(以及对角线的两个总和)
我努力了,但我无法弄清楚那句话的意思。这些数组和总和是如何添加的?谢谢!
enum Piece { Empty, Red, Blue };
enum Check { Row, Column, Diagonal, ReverseDiagonal }
Piece getIthColor(Piece[][] board, int index, int var, Check check) {
if (check == Check.Row) return board[index][var];
else if (check == Check.Column) return board[var][index];
else if (check == Check.Diagonal) return board[var][var];
else if (check == Check.ReverseDiagonal)
return board[board.length - 1 - var][var];
return Piece.Empty;
}
Piece getWinner(Piece[][] board, int fixed_index, Check check) {
Piece color = getIthColor(board, fixed_index, 0, check);
if (color == Piece.Empty) return Piece.Empty;
for (int var = 1; var < board.length; var++) {
if (color != getIthColor(board, fixed_index, var, check)) {
return Piece.Empty;
}
}
return color;
}
Piece hasWon(Piece[][] board) {
int N = board.length;
Piece winner = Piece.Empty;
// Check rows and columns
for (int i = 0; i < N; i++) {
winner = getWinner(board, i, Check.Row);
if (winner != Piece.Empty) {
return winner;
}
winner = getWinner(board, i, Check.Column);
if (winner != Piece.Empty) {
return winner;
}
}
winner = getWinner(board, -1, Check.Diagonal);
if (winner != Piece.Empty) {
return winner;
}
// Check diagonal
winner = getWinner(board, -1, Check.ReverseDiagonal);
if (winner != Piece.Empty) {
return winner;
}
return Piece.Empty;
}
答案 0 :(得分:4)
每次在棋盘中放置一个新棋子时,您将相应的行,列和(可能)对角线计数器增加1.您可以为玩家设置单独的计数器,或使用+ 1 / -1。
现在当您检查电路板时,您只需要检查这些计数器是否等于N,这可以在O(N)
(2N + 2个计数器)中完成。
答案 1 :(得分:2)
它们可能意味着当您放置片段时,您将更新片段所贡献的每个阵列的总和。也就是说,相应的行和列。如果它在对角线上,那么你也会更新它。
在更新方面,如果是红色则添加1,如果是蓝色则减1。如果您的计数从0开始,那么如果该值达到-3或3,您将获胜。