[leetcode] Python(5)--有效的数独(36)、旋转图像(48)

从零开始的力扣(第五天)~

1.有效的数独

判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
    [leetcode] Python(5)--有效的数独(36)、旋转图像(48)_第1张图片
    上图是一个部分填充的有效的数独。数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

示例 1:
输入:
[[“5”,“3”,".",".",“7”,".",".",".","."],
[“6”,".",".",“1”,“9”,“5”,".",".","."],
[".",“9”,“8”,".",".",".",".",“6”,"."],
[“8”,".",".",".",“6”,".",".",".",“3”],
[“4”,".",".",“8”,".",“3”,".",".",“1”],
[“7”,".",".",".",“2”,".",".",".",“6”],
[".",“6”,".",".",".",".",“2”,“8”,"."],
[".",".",".",“4”,“1”,“9”,".",".",“5”],
[".",".",".",".",“8”,".",".",“7”,“9”]]
输出: true

示例 2:
输入:
[[“8”,“3”,".",".",“7”,".",".",".","."],
[“6”,".",".",“1”,“9”,“5”,".",".","."],
[".",“9”,“8”,".",".",".",".",“6”,"."],
[“8”,".",".",".",“6”,".",".",".",“3”],
[“4”,".",".",“8”,".",“3”,".",".",“1”],
[“7”,".",".",".",“2”,".",".",".",“6”],
[".",“6”,".",".",".",".",“2”,“8”,"."],
[".",".",".",“4”,“1”,“9”,".",".",“5”],
[".",".",".",".",“8”,".",".",“7”,“9”]]
输出: false
解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
—————————————————————————————————————————

通过三次遍历,分别遍历行,列,3x3内是否有重复元素

class Solution:
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        # 行中没有重复的数字
        for i in range(9):
            rows = []
            for j in range(9):
                if  board[i][j] in rows:
                    return False
                if board[i][j] != ".":
                    rows.append(board[i][j])            
        # 列中没有重复的数字
        for j in range(9):
            columns = []
            temp = [x[j] for x in board]
            for d in temp:
                if d in columns:
                    return False
                if d != ".":
                    columns.append(d)              
        # 3 x 3 子数独内没有重复的数字
        subs = [[] for i in range(9)]
        for row in range(9):
            for column in range(9):
                box_index = (row // 3) * 3 + column // 3
                if board[row][column] != ".":
                    subs[box_index].append(board[row][column])
        
        for k in subs:
            if len(k) != len(set(k)):
                return False
        return True

在这里插入图片描述
在行列遍历时,我本想通过以下方法来快速完成,但是board是存储多个行list的表,所以在列查找时,下面方法不可以使用,放到下面来提醒自己:

for i in range(9):
            for j in range(1,10):
                if board[i][:].count(j) > 1 or board[:][i].count(j) > 1:
                    return False
                else:
                    continue

还有此行代码是因为将每一个3x3通过行列的规律变为box_index不同的9块,非常巧妙。

box_index = (row // 3) * 3 + column // 3

通过定义新函数来完成3次遍历,减少操作数

很新颖的思路,尤其是最后一次遍历

class Solution:
    def isSingle(self,l):
        d = {}
        for i in l:
            if i != '.':
                if i in d:
                    return False
                else:
                    d[i] = 1
            else:
                continue
        return True

    
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        for l in board:
            if not self.isSingle(l):
                return False
            else:
                continue
        for i in range(9):
            l = [x[i] for x in board]
            if not self.isSingle(l):
                return False
            else:
                continue
        for i in (0,3,6):
            for j in (0,3,6):
                l = board[j][i:i + 3] + board[j + 1][i:i + 3] + board[j + 2][i:i + 3]
                if not self.isSingle(l):
                    return False
        return True

在这里插入图片描述

接下来看一下天才的操作

将[行,值],[列,值],[3x3内,值]作为输出,最后看有无重叠部分。

class Solution(object):
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        seen = sum(([(c, i), (j, c), (i/3, j/3, c)]
                for i, row in enumerate(board)
                for j, c in enumerate(row)
                if c != '.'), [])
        return len(seen) == len(set(seen))

在这里插入图片描述
惊为天人,每当有行或列有两值相同时,在最后的seen输出时会被set删掉重复值。
小tip:sum()函数
在这里插入图片描述
其中后面的[]是sum函数内的初始值,当初始值设为[]时,输出就是将所有情况排列了:
输入:
[[“5”,“3”,".",".",“7”,".",".",".","."],
[“6”,".",".",“1”,“9”,“5”,".",".","."],
[".",“9”,“8”,".",".",".",".",“6”,"."],
[“8”,".",".",".",“6”,".",".",".",“3”],
[“4”,".",".",“8”,".",“3”,".",".",“1”],
[“7”,".",".",".",“2”,".",".",".",“6”],
[".",“6”,".",".",".",".",“2”,“8”,"."],
[".",".",".",“4”,“1”,“9”,".",".",“5”],
[".",".",".",".",“8”,".",".",“7”,“9”]]
seen输出:
[[“5”,0],[0,“5”],[0,0,“5”],[“3”,0],[1,“3”],[0,0,“3”],[“7”,0],[4,“7”],[0,1,“7”],[“6”,1],[0,“6”],[0,0,“6”],[“1”,1],[3,“1”],[0,1,“1”],[“9”,1],[4,“9”],[0,1,“9”],[“5”,1],[5,“5”],[0,1,“5”],[“9”,2],[1,“9”],[0,0,“9”],[“8”,2],[2,“8”],[0,0,“8”],[“6”,2],[7,“6”],[0,2,“6”],[“8”,3],[0,“8”],[1,0,“8”],[“6”,3],[4,“6”],[1,1,“6”],[“3”,3],[8,“3”],[1,2,“3”],[“4”,4],[0,“4”],[1,0,“4”],[“8”,4],[3,“8”],[1,1,“8”],[“3”,4],[5,“3”],[1,1,“3”],[“1”,4],[8,“1”],[1,2,“1”],[“7”,5],[0,“7”],[1,0,“7”],[“2”,5],[4,“2”],[1,1,“2”],[“6”,5],[8,“6”],[1,2,“6”],[“6”,6],[1,“6”],[2,0,“6”],[“2”,6],[6,“2”],[2,2,“2”],[“8”,6],[7,“8”],[2,2,“8”],[“4”,7],[3,“4”],[2,1,“4”],[“1”,7],[4,“1”],[2,1,“1”],[“9”,7],[5,“9”],[2,1,“9”],[“5”,7],[8,“5”],[2,2,“5”],[“8”,8],[4,“8”],[2,1,“8”],[“7”,8],[7,“7”],[2,2,“7”],[“9”,8],[8,“9”],[2,2,“9”]]

2.旋转图像

给定一个 n × n 的二维矩阵表示一个图像。

将图像顺时针旋转 90 度。

说明:

你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。

示例 1:
给定 matrix =
[[1,2,3],
[4,5,6],
[7,8,9]],

原地旋转输入矩阵,使其变为:
[[7,4,1],
[8,5,2],
[9,6,3]]

示例 2:
给定 matrix =
[[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]],

原地旋转输入矩阵,使其变为:
[[15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]]
—————————————————————————————————————————

先进行转置,再左右翻转,可以巧妙解决

class Solution(object):
    def rotate(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        for i in range(len(matrix)):
            for j in range(i):
                matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j]
        for i in range(len(matrix)):
            matrix[i] = matrix[i][::-1]

在这里插入图片描述

先进行上下翻转,再进行转置

class Solution(object):
    def rotate(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        matrix[:] = matrix[::-1]
        for i in range(len(matrix)):
            for j in range(i+1,len(matrix)):
                matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j]

在这里插入图片描述
其实上述转置与翻转可以使用python内置函数zip(*)一行代码完成

class Solution(object):
    def rotate(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        matrix[:] = map(list,zip(*matrix[::-1])) 

在这里插入图片描述
其中zip()函数为压缩函数,zip([seql, …])接受一系列可迭代对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的list(列表),若传入参数的长度不等,则返回list的长度和参数中长度最短的对象相同,而zip(*)可以将已经zip过的列表对象解压。这个用法可以用来实现矩阵的转置。
[leetcode] Python(5)--有效的数独(36)、旋转图像(48)_第2张图片
使用以上方法,还可以通过转置与翻转的顺序不同实现逆时针旋转,就是先进行转置再上下翻转或者先左右翻转再转置。

小tip:

  1. 通过matrix[:] = matrix[::-1]可以轻松实现矩阵上下翻转。
  2. 通过一次小递归matrix[i] = matrix[i][::-1]可以实现矩阵左右翻转。
  3. 还有多种方法实现矩阵旋转,但是因为矩阵根据右上,左下对角线对称的实现方法不如转置方便,所以尽可能选择方便的方法。

以上就是今日经验!

你可能感兴趣的:(leetcode算法)