36&&37 Valid Sudoku&&Sudoku Solver(Hard)

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.

 

暴力解法:

一行一行的看,一列一列的看,一个一个方格的看,

代码如下:

class Solution {
  public:
      bool isValidCell(vector<vector<char> > &board, int a, int b) {
          vector<bool> flag(9, false);
          int idx;
          for (int i = 0; i < 3; ++i) {
              for (int j = 0; j < 3; ++j) {
                  idx = board[a + i][b + j] - '0';
                  if (idx > 0 && idx <= 9 && !flag[idx])  
                     flag[idx] = true;
                 else if (idx > 0 && idx <= 9 && flag[idx])
                     return false;
             }
         }
         return true;
     }
     
     bool isValidRow(vector<vector<char> > &board, int a) {
         vector<bool> flag(9, false);
         int idx;
         for (int j = 0; j < 9; ++j) {
             idx = board[a][j] - '0';
             if (idx > 0 && idx <= 9 && !flag[idx])  
                 flag[idx] = true;
             else if (idx > 0 && idx <= 9 && flag[idx])
                 return false;
         }
         return true;
     }
     
      bool isValidCol(vector<vector<char> > &board, int b) {
         vector<bool> flag(9, false);
         int idx;
         for (int i = 0; i < 9; ++i) {
             idx = board[i][b] - '0';
             if (idx > 0 && idx <= 9 && !flag[idx])  
                 flag[idx] = true;
             else if (idx > 0 && idx <= 9 && flag[idx])
                 return false;
         }
         return true;
     }
     
          bool isValidSudoku(vector<vector<char> > &board) {
         for (int i = 0; i < 3; ++i) {
             for (int j = 0; j < 3; ++j) {
                 if (!isValidCell(board, 3 * i, 3 * j)) 
                     return false;
             }
         }
         for (int i = 0; i < 9; ++i) {
             if (!isValidRow(board, i))
                 return false;
         }
         for (int j = 0; j < 9; ++j) {
             if (!isValidCol(board, j))
                 return false;
         }
         return true;
     }
 };

 

使用Hash思想记录已经出现过的值,这样解法就变的特别容易了:

class Solution {
  public:
    bool isValidSudoku(vector<vector<char> > &board) {
        vector<vector<bool>> rows(9, vector<bool>(9,false));  
        vector<vector<bool>> cols(9, vector<bool>(9,false));  
        vector<vector<bool>> blocks(9, vector<bool>(9,false));  
  
        for(int i = 0; i < 9; i++)  
            for(int j = 0; j < 9; j++)  
            {  
                if(board[i][j] == '.')continue;  
                int num = board[i][j] - '1';  
                if(rows[i][num] || cols[j][num] || blocks[i - i%3 + j/3][num])  
                    return false;  
                rows[i][num] = cols[j][num] = blocks[i - i%3 + j/3][num] = true;  
            }  
        return true;  
     }
 };

 

 

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.

很多题乍一看很难,是因为思路不清晰,只要思路清晰了,还是很简单的。

思路:

首先,每一行每一列的数字不能重合,其次把81个格子分成9个小格子,每一个格子里面的数字不能重合。

转:http://www.cnblogs.com/ganganloveu/p/3828401.html

这题跟N-Queens是一个套路,回溯法尝试所有解。

需要注意的区别是:

本题找到解的处理是return true,因此返回值为bool

N-Queen找到解的处理是保存解,因此返回值为void

 

对于每个空位'.',遍历1~9,check合理之后往下一个位置递归。

由于这里路径尝试本质上是有序的,即1~9逐个尝试,因此无需额外设置状态位记录已经尝试过的方向。

注意:只有正确达到最终81位置(即成功填充)的填充结果才可以返回,若不然,将会得到错误的填充。

因此辅助函数solve需要设为bool而不是void

class Solution {
public:
    void solveSudoku(vector<vector<char> > &board) {
        solve(board, 0);
    }
    bool solve(vector<vector<char> > &board, int position)
    {
        if(position == 81)
            return true;

        int row = position / 9;
        int col = position % 9;
        if(board[row][col] == '.')
        {
            for(int i = 1; i <= 9; i ++)
            {//try each digit
                board[row][col] = i + '0';
                if(check(board, position))
                    if(solve(board, position + 1))
                    //only return valid filling
                        return true;
                board[row][col] = '.';
            }
        }
        else
        {
            if(solve(board, position + 1))
            //only return valid filling
                return true;
        }
        return false;
    }
    bool check(vector<vector<char> > &board, int position)
    {
        int row = position / 9;
        int col = position % 9;
        int gid;
        if(row >= 0 && row <= 2)
        {
            if(col >= 0 && col <= 2)
                gid = 0;
            else if(col >= 3 && col <= 5)
                gid = 1;
            else
                gid = 2;
        }
        else if(row >= 3 && row <= 5)
        {
            if(col >= 0 && col <= 2)
                gid = 3;
            else if(col >= 3 && col <= 5)
                gid = 4;
            else
                gid = 5;
        }
        else
        {
            if(col >= 0 && col <= 2)
                gid = 6;
            else if(col >= 3 && col <= 5)
                gid = 7;
            else
                gid = 8;
        }

        //check row, col, subgrid
        for(int i = 0; i < 9; i ++)
        {
            //check row
            if(i != col && board[row][i] == board[row][col])
                return false;
            
            //check col
            if(i != row && board[i][col] == board[row][col])
                return false;
            
            //check subgrid
            int r = gid/3*3+i/3;
            int c = gid%3*3+i%3;
            if((r != row || c != col) && board[r][c] == board[row][col])
                return false;
        }
        return true;
    }
};

 

  回溯+hash的简介解法:

class Solution {
private:
    bool line[9][9];
    bool column[9][9];
    bool block[3][3][9];
    bool valid;
    vector<pair<int, int>> spaces;

public:
    void dfs(vector<vector<char>>& board, int pos) {
        if (pos == spaces.size()) {
            valid = true;
            return;
        }

        auto [i, j] = spaces[pos];
        for (int digit = 0; digit < 9 && !valid; ++digit) {
            if (!line[i][digit] && !column[j][digit] && !block[i / 3][j / 3][digit]) {
                line[i][digit] = column[j][digit] = block[i / 3][j / 3][digit] = true;
                board[i][j] = digit + '0' + 1;
                dfs(board, pos + 1);
                line[i][digit] = column[j][digit] = block[i / 3][j / 3][digit] = false;
            }
        }
    }

    void solveSudoku(vector<vector<char>>& board) {
        memset(line, false, sizeof(line));
        memset(column, false, sizeof(column));
        memset(block, false, sizeof(block));
        valid = false;

        for (int i = 0; i < 9; ++i) {
            for (int j = 0; j < 9; ++j) {
                if (board[i][j] == '.') {
                    spaces.emplace_back(i, j);
                }
                else {
                    int digit = board[i][j] - '0' - 1;
                    line[i][digit] = column[j][digit] = block[i / 3][j / 3][digit] = true;
                }
            }
        }

        dfs(board, 0);
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/sudoku-solver/solution/jie-shu-du-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  

 

posted @ 2015-09-02 11:08  linqiaozhou  阅读(251)  评论(0编辑  收藏  举报