遍历有效数独的子框

时间:2019-04-08 09:41:29

标签: python

我正在研究Valid Sudoku - LeetCode 并且无法弄清楚为什么box_index = (i // 3 ) * 3 + j // 3能够遍历子框

  

确定9x9数独板是否有效。只有填充的单元格需要根据以下规则进行验证:

     
      
  1. 每行必须包含数字1-9,且不能重复。
  2.   
  3. 每列必须包含数字1-9,且不能重复。
  4.   
  5. 网格的9个3x3子框中的每个子框中都必须包含数字1-9,且不能重复。
  6.   
     

enter image description here   有效的部分数独。

     

数独板可能会部分填充,其中的空白单元格中会填充字符'.'

     

示例1:

Input:
[
  ["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"]
]
Output: true
     

示例2:

Input:
[
  ["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"]
]
Output: false
Explanation: Same as Example 1, except with the 5 in the top left corner being 
    modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
     

注意:

     
      
  • 数独板(部分填充)可能有效,但不一定可以解决。
  •   
  • 仅需根据所提到的规则验证填充的单元格。
  •   
  • 给定的面板仅包含数字1-9和字符'.'
  •   
  • 给定的木板尺寸始终为9x9
  •   

阅读明智的解决方案

class Solution:
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        # init data
        rows = [{} for i in range(9)]
        columns = [{} for i in range(9)]
        boxes = [{} for i in range(9)]

        # validate a board
        for i in range(9):
            for j in range(9):
                num = board[i][j]
                if num != '.':
                    num = int(num)
                    box_index = (i // 3 ) * 3 + j // 3

                    # keep the current cell value
                    rows[i][num] = rows[i].get(num, 0) + 1
                    columns[j][num] = columns[j].get(num, 0) + 1
                    boxes[box_index][num] = boxes[box_index].get(num, 0) + 1

                    # check if this value has been already seen before
                    if rows[i][num] > 1 or columns[j][num] > 1 or boxes[box_index][num] > 1:
                        return False         
        return True

TestCase

class MyCase(unittest.TestCase):
   class MyCase(unittest.TestCase):
    def setUp(self):
        self.solution = Solution()

    def test_a(self):
        board = [   ["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"]
                ]
        check = self.solution.isValidSudoku(board)
        self.assertTrue(check)

    def test_b(self):
        board = [   ["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"]
                ]
        check = self.solution.isValidSudoku(board)
        self.assertFalse(check)

unittest.main() def setUp(self):
        self.solution = Solution()

    def test_a(self):
        board = [   ["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"]
                ]
        check = self.solution.isValidSudoku(board)
        self.assertTrue(check)

    def test_b(self):
        board = [   ["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"]
                ]
        check = self.solution.isValidSudoku(board)
        self.assertFalse(check)

unittest.main()

您能否提供任何提示,说明box_index = (i // 3 ) * 3 + j // 3为何可以遍历子框?

1 个答案:

答案 0 :(得分:1)

您可以将整个框拆分为3*3子框,(i, j)属于索引为(i//3, j//3)的子框,这是3*3 2D阵列。如果我们想将其展平为1*9一维数组,则索引将为(i // 3 ) * 3 + j // 3

具有索引的子框:

|0|1|2|
|3|4|5|
|6|7|8|

如果您仍然感到困惑,可以尝试一些示例,并弄清楚。

希望对您有所帮助,如果还有其他问题,请发表评论。 :)