LeetCode 探索初级算法-数组:10 有效的数独-20200321

10 有效的数独-20200321

题目

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

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

数独部分空格内已填入了数字,空白格用 '.' 表示。

示例

输入:
[
  ["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

说明

  • 一个有效的数独(部分已被填充)不一定是可解的。
  • 只需要根据以上规则,验证已经填入的数字是否有效即可。
  • 给定数独序列只包含数字 1-9 和字符 '.' 。
  • 给定数独永远是 9x9 形式的。

注意事项

  1. 数独的形式永远都是9x9。
  2. 空格用字符 '.'来代替了。
  3. 每个3x3的数组有5个数字,所以1-9每个数字都要出现5次。也就是说每个数字的重复次数等于5。 不对!!

思路一

用四个指针i,j,k,h做。三个判断设置用和三个字典single、row和column实现。数组来存储各个3*3的元素是否存在的指示。字典用来判断每行每列的重复元素。

  1. 判断字典single[nums[i,j]]是否为1,同时判断字典row[nums[i,j]]的数组中是否有i,字典colum[nums[i,j]的数组中是否有j。如果有一项不成立就返回False。否则字典存入相应项,并j加一。j在range(h,h+3)。
  2. 判断j是否等于2,5,8。如果等于就重置字典single,h+=3,否则pass。
  3. i循环range(k,k+3),循环完毕就k+=3。

修改经历:

1. 在判断时,把元素当做行列的index了。(第一次提交)

  • 解答错误

2. 修改过后,提交成功。(第二次提交)

  • 执行用时 :48 ms, 在所有 Python3 提交中击败了92.28%的用户
  • 内存消耗 :13.6 MB, 在所有 Python3 提交中击败了5.03%的用户

心得体会:

  1. 注意 i = j = 0 和 i, j =0, 0的区别,前者相当于两个指针指向一个地址,后者是两个指针指向两个地址。同理列表,字典等都是一样的。
  2. 还有 list 和 narray 的区别,前者是[i][j]取元素,后者是[i,j]取元素。
  3. 这个思路真的是很垃圾,其实这不是列表呢,直接取出来每行每列判断就好,难点就在怎么判断3*3的矩阵。
  4. 字典可以这么写 
    rows = [{} for i in range(9)]

最终代码展示:

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        i, j, k, h = 0, 0, 0, 0
        single = {0:[], 1:[], 2:[], 3:[], 4:[], 5:[], 6:[], 7:[], 8:[], 9:[]}
        row = {0:[], 1:[], 2:[], 3:[], 4:[], 5:[], 6:[], 7:[], 8:[], 9:[]}
        column = {0:[], 1:[], 2:[], 3:[], 4:[], 5:[], 6:[], 7:[], 8:[], 9:[]}
        for k in range(0, 9, 3):
            for h in range(0, 9, 3):
                for i in range(k, k+3):
                    for j in range(h, h+3):
                        if board[i][j] != '.':
                            item = int(board[i][j])
                            if 1 not in single[item] and i not in row[item] and j not in column[item]:
                                single[item] += [1]
                                row[item] += [i]
                                column[item] += [j]
                            else:
                                return False
                        else:
                            pass
                single = {0:[], 1:[], 2:[], 3:[], 4:[], 5:[], 6:[], 7:[], 8:[], 9:[]}
        return True

思路二

这次直接取出来判断。不要一个一个元素进行判断。比较难判断的就是每一小块怎么判断。找到每一块的index与循环次数的关系就好。n=[0,1,...,8],则Z形排列的小块的index为,横坐标=[3*int(n/3):3*int(n/3)+3],纵坐标=[3*int(n%3):3*int(n%3)+3]。

修改经历:

1. 写了半天,or写成and了。。。(第一次提交)

  • 解答错误

2. 修改过提交成功。(第二次提交)

  • 执行用时 :124 ms, 在所有 Python3 提交中击败了23.89%的用户
  • 内存消耗 :13.6 MB, 在所有 Python3 提交中击败了5.03%的用户

心得体会:

  1. 一定要注意列表的切片与narray不同!!!A=[[1,2],[3,4]]要取出[1,3]要单独在每一个list里取相应index的值。A[:][0]与A[:][0]都是[1,2]。[x[0] for x in A]才行。
  2. 怎么还慢了呢?

最终代码展示:

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        for n in range(1, 10):
            for k in range(0, 9):
                column = [x[k] for x in board]
                temp = [x[3*int(k%3):3*int(k%3)+3] for x in board[3*int(k/3):3*int(k/3)+3]]
                block = []
                for item in temp:
                    block += item
                if board[k][:].count(str(n)) > 1 or column.count(str(n)) > 1 or block.count(str(n)) > 1:
                    return False
        return True
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值