• leetcode 37. Sudoku Solver 36. Valid Sudoku 数独问题


    三星机试也考了类似的题目,只不过是要针对给出的数独修改其中三个错误数字,总过10个测试用例只过了3个与世界500强无缘了

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


    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.

    Subscribe to see which companies asked this question


    Idea

    Just go through all you see (like "7 in row 3") and check for duplicates.

    Solution 1

    Using Counter. One logical line, seven physical lines.

    def isValidSudoku(self, board):
        return 1 == max(collections.Counter(
            x
            for i, row in enumerate(board)
            for j, c in enumerate(row)
            if c != '.'
            for x in ((c, i), (j, c), (i/3, j/3, c))
        ).values() + [1])
    

    The + [1] is only for the empty board, where max would get an empty list and complain. It's not necessary to get it accepted here, as the empty board isn't among the test cases, but it's good to have.

    Solution 2

    Using len(set).

    def isValidSudoku(self, board):
        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))
    

    Solution 3

    Using any.

    def isValidSudoku(self, board):
        seen = set()
        return not any(x in seen or seen.add(x)
                       for i, row in enumerate(board)
                       for j, c in enumerate(row)
                       if c != '.'
                       for x in ((c, i), (j, c), (i/3, j/3, c)))
    

    Solution 4

    Iterating a different way.

    def isValidSudoku(self, board):
        seen = sum(([(c, i), (j, c), (i/3, j/3, c)]
                    for i in range(9) for j in range(9)
                    for c in [board[i][j]] if c != '.'), [])
        return len(seen) == len(set(seen))

    Clean and Easy82ms Python

    +11votes
    402 views

    class Solution(object):

    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        big = set()
        for i in xrange(0,9):
            for j in xrange(0,9):
                if board[i][j]!='.':
                    cur = board[i][j]
                    if (i,cur) in big or (cur,j) in big or (i/3,j/3,cur) in big:
                        return False
                    big.add((i,cur))
                    big.add((cur,j))
                    big.add((i/3,j/3,cur))









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


    ...and its solution numbers marked in red.

    Subscribe to see which companies asked this question

    最快的解决方案:


    Sharing my 2ms C++ solution with comments and explanations.

    +37votes
    3,937 views

    Update: there's a follow-up 0ms solution which is even more optimized

    This is one of the fastest Sudoku solvers I've ever written. It is compact enough - just 150 lines of C++ code with comments. I thought it'd be interesting to share it, since it combines several techniques like reactive network update propagation and backtracking with very aggressive pruning.

    The algorithm is online - it starts with an empty board and as you add numbers to it, it starts solving the Sudoku.

    Unlike in other solutions where you have bitmasks of allowed/disallowed values per row/column/square, this solution track bitmask for every(!) cell, forming a set of constraints for the allowed values for each particular cell. Once a value is written into a cell, new constraints are immediately propagated to row, column and 3x3 square of the cell. If during this process a value of other cell can be unambiguously deduced - then the value is set, new constraints are propagated, so on.... You can think about this as an implicit reactive network of cells.

    If we're lucky (and we'll be lucky for 19 of 20 of Sudokus published in magazines) then Sudoku is solved at the end (or even before!) processing of the input.

    Otherwise, there will be empty cells which have to be resolved. Algorithm uses backtracking for this purpose. To optimize it, algorithm starts with the cell with the smallest ambiguity. This could be improved even further by using priority queue (but it's not implemented here). Backtracking is more or less standard, however, at each step we guess the number, the reactive update propagation comes back into play and it either quickly proves that the guess is unfeasible or significantly prunes the remaining search space.

    It's interesting to note, that in this case taking and restoring snapshots of the compact representation of the state is faster than doing backtracking rollback by "undoing the moves".

    class Solution {
        struct cell // encapsulates a single cell on a Sudoku board
        {
            uint8_t value; // cell value 1..9 or 0 if unset
            // number of possible (unconstrained) values for the cell
            uint8_t numPossibilities;
            // if bitset[v] is 1 then value can't be v
            bitset<10> constraints;
            cell() : value(0), numPossibilities(9),constraints() {};
        };
        array<array<cell,9>,9> cells;
    
        // sets the value of the cell to [v]
        // the function also propagates constraints to other cells and deduce new values where possible
        bool set(int i, int j, int v)
        { 
            // updating state of the cell
            cell& c = cells[i][j];
            if (c.value == v)
                return true;
            if (c.constraints[v])
                return false;
            c.constraints = bitset<10>(0x3FE); // all 1s
            c.constraints.reset(v);
            c.numPossibilities = 1;
            c.value = v;
    
            // propagating constraints
            for (int k = 0; k<9; k++) {
                // to the row: 
                if (i != k && !updateConstraints(k, j, v))
                    return false;
                // to the column:
                if (j != k && !updateConstraints(i, k, v))
                    return false;
                // to the 3x3 square:
                int ix = (i / 3) * 3 + k / 3;
                int jx = (j / 3) * 3 + k % 3;
                if (ix != i && jx != j && !updateConstraints(ix, jx, v))
                    return false;
            }
            return true;
        }
        // update constraints of the cell i,j by excluding possibility of 'excludedValue'
        // once there's one possibility left the function recurses back into set()
        bool updateConstraints(int i, int j, int excludedValue)
        {
            cell& c = cells[i][j];
            if (c.constraints[excludedValue]) {
                return true;
            }
            if (c.value == excludedValue) {
                return false;
            }
            c.constraints.set(excludedValue);
            if (--c.numPossibilities > 1)
                return true;
            for (int v = 1; v <= 9; v++) {
                if (!c.constraints[v]) {
                    return set(i, j, v);
                }
            }
            assert(false);
        }
    
        // backtracking state - list of empty cells
        vector<pair<int, int>> bt;
    
        // find values for empty cells
        bool findValuesForEmptyCells()
        {
            // collecting all empty cells
            bt.clear();
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    if (!cells[i][j].value)
                        bt.push_back(make_pair(i, j));
                }
            }
            // making backtracking efficient by pre-sorting empty cells by numPossibilities
            sort(bt.begin(), bt.end(), [this](const pair<int, int>&a, const pair<int, int>&b) {
                return cells[a.first][a.second].numPossibilities < cells[b.first][b.second].numPossibilities; });
            return backtrack(0);
        }
    
        // Finds value for all empty cells with index >=k
        bool backtrack(int k)
        {
            if (k >= bt.size())
                return true;
            int i = bt[k].first;
            int j = bt[k].second;
            // fast path - only 1 possibility
            if (cells[i][j].value)
                return backtrack(k + 1);
            auto constraints = cells[i][j].constraints;
            // slow path >1 possibility.
            // making snapshot of the state
            array<array<cell,9>,9> snapshot(cells);
            for (int v = 1; v <= 9; v++) {
                if (!constraints[v]) {
                    if (set(i, j, v)) {
                        if (backtrack(k + 1))
                            return true;
                    }
                    // restoring from snapshot,
                    // note: computationally this is cheaper
                    // than alternative implementation with undoing the changes
                    cells = snapshot;
                }
            }
            return false;
        }
    public:
        void solveSudoku(vector<vector<char>> &board) {
            cells = array<array<cell,9>,9>(); // clear array
            // Decoding input board into the internal cell matrix.
            // As we do it - constraints are propagated and even additional values are set as we go
            // (in the case if it is possible to unambiguously deduce them).
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++) {
                    if (board[i][j] != '.' && !set(i, j, board[i][j] - '0'))
                        return; // sudoku is either incorrect or unsolvable
                }
            }
            // if we're lucky we've already got a solution,
            // however, if we have empty cells we need to use backtracking to fill them
            if (!findValuesForEmptyCells())
                return; // sudoku is unsolvable
    
            // copying the solution back to the board
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++) {
                    if (cells[i][j].value)
                        board[i][j] = cells[i][j].value + '0';
                }
            }
        }
    };





















    Simple and Clean Solution / C++

    +14votes
    871 views
    bool check(vector<vector<char>> &board, int i, int j, char val)
    {
        int row = i - i%3, column = j - j%3;
        for(int x=0; x<9; x++) if(board[x][j] == val) return false;
        for(int y=0; y<9; y++) if(board[i][y] == val) return false;
        for(int x=0; x<3; x++)
        for(int y=0; y<3; y++)
            if(board[row+x][column+y] == val) return false;
        return true;
    }
    bool solveSudoku(vector<vector<char>> &board, int i, int j)
    {
        if(i==9) return true;
        if(j==9) return solveSudoku(board, i+1, 0);
        if(board[i][j] != '.') return solveSudoku(board, i, j+1);
    
        for(char c='1'; c<='9'; c++)
        {
            if(check(board, i, j, c))
            {
                board[i][j] = c;
                if(solveSudoku(board, i, j+1)) return true;
                board[i][j] = '.';
            }
        }
    
        return false;
    }
    

    public: void solveSudoku(vector<vector>& board) { solveSudoku(board, 0, 0); }


    c++ clear solution using dfs, beating 90% c++ coder.

    +10votes
    690 views
    class Solution {
    public:
        bool col[10][10],row[10][10],f[10][10];
        bool flag = false;
        void solveSudoku(vector<vector<char>>& board) {
             memset(col,false,sizeof(col));
             memset(row,false,sizeof(row));
             memset(f,false,sizeof(f));
             for(int i = 0; i < 9;i++){
                 for(int j = 0; j < 9;j++){
                     if(board[i][j] == '.')   continue;
                     int temp = 3*(i/3)+j/3;
                     int num = board[i][j]-'0';
                     col[j][num] = row[i][num] = f[temp][num] = true;
                 }
             }
             dfs(board,0,0);
        }
        void dfs(vector<vector<char>>& board,int i,int j){
            if(flag == true)  return ;
            if(i >= 9){
                flag = true;
                return ;
            }
            if(board[i][j] != '.'){
                 if(j < 8)  dfs(board,i,j+1);
                 else dfs(board,i+1,0);
                 if(flag)  return;
            }
    
            else{
                int temp = 3*(i/3)+j/3;
                for(int n = 1; n <= 9; n++){
                    if(!col[j][n] && !row[i][n] && !f[temp][n]){
                        board[i][j] = n + '0';
                        col[j][n] = row[i][n] = f[temp][n] = true;
                        if(j < 8)  dfs(board,i,j+1);
                        else dfs(board,i+1,0);
                        col[j][n] = row[i][n] = f[temp][n] = false;
                        if(flag)  return;
                    }
                }
                board[i][j] = '.';
            }
        }
    };









































    13-line Python solution, dfs, beats 47.79%

    +1vote
    77 views
    def solveSudoku(self, board):
      def dfs():
        for i, row in enumerate(board):
          for j, char in enumerate(row):
            if char == '.':
              for x in s9 - {row[k] for k in r9} - {board[k][j] for k in r9} - 
                  {board[i / 3 * 3 + m][j / 3 * 3 + n] for m in r3 for n in r3}:
                board[i][j] = x
                if dfs(): return True
                board[i][j] = '.'
              return False
        return True
    
      r3, r9, s9 = range(3), range(9), {'1', '2', '3', '4', '5', '6', '7', '8', '9'}
      dfs()












    参考文献:


    http://www.cnblogs.com/felixfang/p/3705754.html

  • 相关阅读:
    数据库设计时间修饰词
    Tomcat手动指定jdk路径
    linux删除乱码文件[转载]
    elasticsearch简单查询
    elasticsearch批量删除(查询删除)
    elasticsearch使用Analyze API
    elasticsearch批量索引数据示例
    Elasticsearch创建索引和映射结构详解
    mysql设置服务器编码
    HBase单机模式安装
  • 原文地址:https://www.cnblogs.com/wangyaning/p/7853902.html
Copyright © 2020-2023  润新知