[几个Python技巧]Valid Sudoku
一、题目
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.
The Sudoku board could be partially filled, where empty cells are filled with the character '.'
.
二、解析
判断给定的数独是否满足规则,即每行中没有重复元素、每列中没有重复元素、每个3*3的块中也没有重复元素
思路很简单,暴力即可,但从这题中学到了好多个技巧。
方法1是纯粹的遍历,当然效率也不高,超越27%;方法2经过改写,思路一样,超越81%
三、代码
方法1
class Solution(object): def isValidSudoku(self, board): """ :type board: List[List[str]] :rtype: bool """ for i in range(9): cur = [] for j in range(9): #check line if board[i][j] in cur: return False else: if board[i][j] != ".": cur.append(board[i][j]) else: pass lenCur = len(cur) lenSet = len(set(cur)) if lenCur != lenSet: return False else: pass for i in range(9): cur = [] for j in range(9): #check col if board[j][i] in cur: return False else: if board[j][i] != ".": cur.append(board[j][i]) else: pass lenCur = len(cur) lenSet = len(set(cur)) if lenCur != lenSet: return False else: pass for a in range(0, 9, 3): for b in range(0, 9, 3): cur = [] for i in range(a, a + 3, 1): for j in range(b, b + 3, 1): if board[i][j] in cur: return False else: if board[i][j] != ".": cur.append(board[i][j]) else: pass lenCur = len(cur) lenSet = len(set(cur)) if lenCur != lenSet: return False else: pass return True
可以看出,方法1中纯粹是遍历了9*9中的每个元素,用原始的list, set等操作来解决。
方法2:
class Solution(object): def isValidSudoku(self, board): """ :type board: List[List[str]] :rtype: bool """ for row in board: if not self.isValid(row): return False for col in zip(*board): if not self.isValid(col): return False for i in (0, 3, 6): for j in (0, 3, 6): square = [board[x][y] for x in range(i, i + 3) for y in range(j, j + 3)] if not self.isValid(square): return False return True def isValid(self, s): unit = [i for i in s if i != '.'] return len(unit) == len(set(unit))
四、总结
1.以后再遇到通过遍历得到list的过程,使用lambda表达式写,如:
unit = [i for i in s if i != '.']
2.对于已经是list的数据类型,不要再重复遍历了,直接对其进行操作即可,如:
for row in board, 这里board是[[],[],...],row是[]
3.能不开变量就不要开变量,如:
rst = self.isValid(row)
if not rst:
return False
应写程
if not self.isValid(row):
return False
虽然只是很小一步,但是就从超越60%上升到了80%。
5.遍历大法:
for index, content in enumurate(board): index是索引,content是值。等同于for i in range(len(board)):print i, board[i],好看许多
6.zip:拉链函数
board1=[[1,2,3],[4,5,6],[7,8,9]]
board2=[[9,8,7],[6,5,4],[3,2,1]]
zip(board1, board2):[([1, 2, 3], [9, 8, 7]), ([4, 5, 6], [6, 5, 4]), ([7, 8, 9], [3, 2, 1])]
zip将两个可迭代的(tumple, list, set, dict)上下对比粘合到一起
board1=[[1,2,3],[4,5,6],[7,8,9]]
zip(*board),可实现上下匹配,即(147),(258),(369),正是我要的列向量。
zip(board),仅仅是变成元组,即(123),(456),(789)
今后再写代码刷题,不单要实现功能和优化算法,更要让程序看起来很美,美=可读性+简洁。OK继续加油!