leetcode36&37_SudukuSolver

橘子oly發表於2016-11-07

36題:

一.問題描述

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 '.'.


A partially filled sudoku which is valid.

Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.

即判斷當前部分填充的數獨是否是有效的,即每一列,每一行,每一個九宮格內沒有重讀的數字。

二.程式碼編寫

主要思想就是為每一行,每一列,每一個九宮格建立一個flag列表,然後遍歷整個數獨矩陣,去填充flag列表。flag列表內的每個元素是一個整數,

每次遍歷到的非'.'數字,則對相應flag列表的int做加法,x = 10**int(board[i][j]),這樣最後得到的int的大於1的位置則代表該列/行/九宮格內有重複數字,

則該數獨矩陣不合法。程式碼如下:

import math
class Solution(object):
    def is_ok(self,x):
        '''
        type x: int
        rtype: bool
        '''
        for i in str(x):
            if i=='0' or i=='1':
                continue
            else:
                return False
        return True
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        len_bo = len(board)
        len_bo_sq = int(math.sqrt(len_bo))
        H = [0 for i in range(len_bo)]
        S = [0 for i in range(len_bo)]
        Z = [[0 for i in range(len_bo_sq)] for j in range(len_bo_sq)]
        for i in range(len_bo):
            for j in range(len_bo):
                if board[i][j] == '.':
                    continue
                x = 10**int(board[i][j])
                H[i] += x
                S[j] += x
                Z[i/3][j/3] += x
        for i in range(len_bo):
            if self.is_ok(H[i]) == False:
                return False
            if self.is_ok(S[i]) == False:
                return False
        for i in range(len_bo_sq):
            for j in range(len_bo_sq):
                if self.is_ok(Z[i][j]) == False:
                    return False
        return True
對上述題目描述中的矩陣而言,其三個flag列表值如下:
行:H = [0010101000,
     1001100010,
     1101000000,
     0101001000,
     0100011010,
     0011000100,
     0101000100,
     1000110010,
     1110000000]

列:略- -
九宮格:Z=[

   [1101101000,1010100010,0001000000],
   [0110010000,0101001100,0001001010],
   [0001000000,1100010010,1110100100]
  ]

37.Sudoku Solver

一.問題描述:

Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character '.'.

You may assume that there will be only one unique solution.


A sudoku puzzle...

對數獨求解,基本規則使最後填滿的數獨是valid即可,假設解是唯一的。

二.程式碼編寫:

典型的回溯思想(DFS)求解,(類似於走迷宮,走不下去了就回溯),具體思想就是對空格子由1到9填充(這裡首先要選擇當前位置的valid解),

填好了之後填下一個。

演算法編寫的思想就是從第一個位置開始找,如果該位置不為空,則對該位置進行填充,如果填充之後數獨是valid的話,再判斷之後的剩下位置是否valid(遞迴演算法)。

判斷valid我本來直接用的36的演算法,結果TLE了,上網搜了一下發現可以優化valid的演算法。也就是說只要判斷當前填充進來的數字是否在對應行、列、九宮格中已經存在,

只要存在就返回False。程式碼如下:

class Solution(object):
    def isValidSudoku(self, board,row,col,s):
         # 只要判斷當前加進去的[row][col]位置的數字是否valid即可,因為之前的數獨是valid的
         # 也就是隻要判斷row行沒有s,col列沒有s,九宮格內沒有s即可
        """
        :type board: List[List[str]]
        :type row: int
        :type col: int
        :type s: str
        :rtype: bool
        """
        len_board = len(board)
        for i in range(len_board):
            if board[row][i] == s:
                return False
            if board[i][col] == s:
                return False
        m = 3*(row/3)
        n = 3*(col/3)
        for i in range(m, m+3):
            for j in range(n, n+3):
                if board[i][j] == s:
                    return False
        return True

    def dfs(self, board, row, col):
        len_board = len(board)
        if col >= len_board:
            row += 1
            col = 0
        if row >= len_board:
            return True
        if board[row][col] == '.':
            for i in range(1, 10):
                #board[row][col] = str(i)
                if self.isValidSudoku(board,row,col,str(i)) == True:
                    board[row][col] = str(i)
                    if self.dfs(board, row, col + 1) == True:
                        return True
                    board[row][col] = '.'
            return False
        else:
            return self.dfs(board, row, col+1)
        return False

    def solveSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: void Do not return anything, modify board in-place instead.
        """
        self.dfs(board, 0, 0)