一、原题
二、解法
1、个人思路
看到这道题目后没有想到什么简单有效的方法,于是直接暴力求解:依次处理每一行、每一列以及两条对角线上的字符即可,代码如下:
class Solution(object):
def tictactoe(self, board):
"""
:type board: List[str]
:rtype: str
"""
N = len(board[0])
# 处理每一行
for i in range(N):
for j in range(1, N):
if board[i][j] != board[i][0]:
break
else:
if board[i][0] != " ":
return board[i][0]
# 处理每一列
for i in range(N):
for j in range(1, N):
if board[j][i] != board[0][i]:
break
else:
if board[0][i] != " ":
return board[0][i]
# 主对角线
for i in range(1, N):
if board[i][i] != board[0][0]:
break
else:
if board[0][0] != " ":
return board[0][0]
# 副对角线
for i in range(1, N):
if board[i][N-1-i] != board[0][N-1]:
break
else:
if board[0][N-1] != " ":
return board[0][N-1]
# 判断棋盘上是否还有空位
for val in board:
if val.find(" ") != -1:
return "Pending"
return "Draw"
意外的是,没想到如此“朴素”的解法在内存消耗和用时上表现还比较好。
2、题解中他人思路
(1) any()函数
在python中,函数any()接收一个可迭代的参数iter,若iter中的元素都为False,则any()函数返回False;若至少有一个元素为True,则any()函数返回True。元素除了0、“”(空)或者False时 都看作为True。
print(any([1, 0, 5])) # True
print(any([0, 0, 0])) # False
print(any([False, False, True])) # True
print(any(("", "a", ""))) # True
print(any(("", "" ,""))) # False
print(any([])) # Flase
(2)python中*的使用情况总结
a、作为乘号
print(5*8) # 输出40
b、*号后面的数字表示重复的次数
print([0, 'c']*3) # [0, 'c', 0, 'c', 0, 'c']
c、调用函数时实参前加*
如下代码中我们定义了函数test,test会接收三个实参;同时定义了一个有三个元素的列表a,若我们想将a中的元素作为实参传给test,可直接执行test(*a)。
即若将*放于可迭代的变量(List、元组、字典等)前,则它会将变量中的值依次取出。
def test(a, b, c):
pass
a = [1, 2, 3]
test(*a) # 等价于test(a[0], a[1], a[2])
d、定义函数时,形参前加*
def test(a, b, *args):
print(a)
print(b)
print(args)
print(type(args))
test(1, 2, 3, 4, 5)
代码执行的结果为:
1
2
(3, 4, 5)
<class 'tuple'>
分析可知,执行test(1, 2, 3, 4, 5)以后,将1赋给了形参a,2赋给了形参b,而剩下的实参3、4、5三个数则一起赋给了形参args,且args的类型是一个元组。因此,在定义函数时,若形参前加*,则我们可以将该形参理解为一个元组。
(3)、python中**的的使用情况总结
a、可将" a**n"理解为求a的n次方
print(5**3) # 125
b、定义函数时形参前使用**
def test(**args):
print(type(args))
print(args)
test(a=1, b=2, c=3)
代码的执行结果为:
<class 'dict'>
{'a': 1, 'b': 2, 'c': 3}
可知,若在形参前使用**,则说明这个形参是一个字典。
c、实参前使用**
def test(a, b, c):
print(a)
print(b)
print(c)
dict = {a:1, b:2, c:3}
test(**dict)
执行代码,输出为:
1
2
3
(4)zip()函数
python3中,该函数接收可迭代的对象作为参数,将各个对象中的元素打包成一个个元组,并返回由这些元组组成的对象。
a = [1, 2, 3]
b = [4, 5, 6]
zipped = zip(a, b)
# print(tuple(zipped)) #将zipped转换为元组输出
print(list(zipped)) #将zipped转换为列表输出
执行代码,结果为:
[(1, 4), (2, 5), (3, 6)]
有了以上基础,我们可以理解以下代码了:
def tictactoe(self, board: List[str]) -> str:
N = len(board[0])
def exist(c):
string = c * N
return any((
# 处理行
any(string == line for line in board),
# 处理列
any(string == col for col in map(''.join, zip(*board))),
# 处理主对角线
all(c == board[i][i] for i in range(N)),
# 处理副对角线
all(c == board[i][N-1-i] for i in range(N))
)
)
if exist("O") == True:
return "O"
if exist("X") == True:
return "X"
# for line in board:
# if line.find(" ") != -1:
# return "Pending"
if " " in "".join(board):
return "Pending"
return "Draw"