边工作边刷题:70天一遍leetcode: day 95-2
Design Tic-Tac-Toe
要点:这题和design题接近,重点是如何表示,从而便于计算game状态。巧妙的方法是只用list[i]表示某行/列,两个players分别从+/-两个方向累加,哪个位置累加到n/-n则代表哪个player胜出。当然还有对角线/反对角线的情况
- 和8-queen,sudoku的区别?
- 首先这题的目标是count,而8-queen/sudoku是occurrence。所以每个行/列都要用一个元素表示count,所以最终是2个list。8-queen只有列需要用list,相当于是inverse的:记录了每列的占用情况。而sudoku是某个数(val)在某行/列是否已经用过,所以是2d boolean数组。
- 斜向只有对角线和反对角线的格子数和行列是相同的,所以只有2个变量表示
# Design a Tic-tac-toe game that is played between two players on a n x n grid.
# You may assume the following rules:
# A move is guaranteed to be valid and is placed on an empty block.
# Once a winning condition is reached, no more moves is allowed.
# A player who succeeds in placing n of their marks in a horizontal, vertical, or diagonal row wins the game.
# Example:
# Given n = 3, assume that player 1 is "X" and player 2 is "O" in the board.
# TicTacToe toe = new TicTacToe(3);
# toe.move(0, 0, 1); -> Returns 0 (no one wins)
# |X| | |
# | | | | // Player 1 makes a move at (0, 0).
# | | | |
# toe.move(0, 2, 2); -> Returns 0 (no one wins)
# |X| |O|
# | | | | // Player 2 makes a move at (0, 2).
# | | | |
# toe.move(2, 2, 1); -> Returns 0 (no one wins)
# |X| |O|
# | | | | // Player 1 makes a move at (2, 2).
# | | |X|
# toe.move(1, 1, 2); -> Returns 0 (no one wins)
# |X| |O|
# | |O| | // Player 2 makes a move at (1, 1).
# | | |X|
# toe.move(2, 0, 1); -> Returns 0 (no one wins)
# |X| |O|
# | |O| | // Player 1 makes a move at (2, 0).
# |X| |X|
# toe.move(1, 0, 2); -> Returns 0 (no one wins)
# |X| |O|
# |O|O| | // Player 2 makes a move at (1, 0).
# |X| |X|
# toe.move(2, 1, 1); -> Returns 1 (player 1 wins)
# |X| |O|
# |O|O| | // Player 1 makes a move at (2, 1).
# |X|X|X|
# Follow up:
# Could you do better than O(n2) per move() operation?
# Hint:
# Could you trade extra space such that move() operation can be done in O(1)?
# You need two arrays: int rows[n], int cols[n], plus two variables: diagonal, anti_diagonal.
class TicTacToe(object):
def __init__(self, n):
"""
Initialize your data structure here.
:type n: int
"""
self._n = n
self._rowcount = [0]*n
self._colcount = [0]*n
self._diag = 0
self._rdiag = 0
def move(self, row, col, player):
"""
Player {player} makes a move at ({row}, {col}).
@param row The row of the board.
@param col The column of the board.
@param player The player, can be either 1 or 2.
@return The current winning condition, can be either:
0: No one wins.
1: Player 1 wins.
2: Player 2 wins.
:type row: int
:type col: int
:type player: int
:rtype: int
"""
add = 1 if player==1 else -1
self._rowcount[row]+=add
self._colcount[col]+=add
if row==col:
self._diag+=add
if row==self._n-1-col:
self._rdiag+=add
if self._diag==self._n*add or self._rdiag==self._n*add or \
self._rowcount[row]==self._n*add or self._colcount[col]==self._n*add:
return player
return 0
# Your TicTacToe object will be instantiated and called as such:
# obj = TicTacToe(n)
# param_1 = obj.move(row,col,player)