美文网首页
[leetcode] 36 有效数独

[leetcode] 36 有效数独

作者: Kevifunau | 来源:发表于2018-10-20 08:06 被阅读0次

leetcode 36

Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:
Each row must contain the digits 1-9 without repetition.
Each column must contain the digits 1-9 without repetition.
Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition.


image.png

The Sudoku board could be partially filled, where empty cells are filled with the character '.'.
Example 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
Example 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.
Note:
A Sudoku board (partially filled) could be valid but is not necessarily solvable.
Only the filled cells need to be validated according to the mentioned rules.
The given board contain only digits 1-9 and the character '.'.
The given board size is always 9x9.

有效数独

题目的意思就是 保证
每行
每列
每3x3 的小方格 内 不允许出现重复数字
于是乎 ,我就依次检查
每行
每列
每3x3
..............
这题应该有啥优雅的写法,我先写个不用动脑的。。

#include <unordered_map>

using namespace std;
class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        //row
        for(int i = 0; i < 9; i++){
            up.clear();
            for(int j = 0; j < 9;j++){
                up[board[i][j]]++;
                if( board[i][j] !='.' && up[board[i][j]] > 1 )
                    return false;
            }
        }
        
        // column
        for(int i = 0; i < 9; i++){
            up.clear();
            for(int j = 0; j < 9;j++){
                up[board[j][i]]++;
                if( board[j][i] !='.' && up[board[j][i]] > 1 )
                    return false;
            }
        }
        // 3X3
        for(int i = 0; i < 9 ; i+=3){
            for(int j = 0; j < 9; j+=3){
                if (!isValid33(board, i,j))
                    return false; 
            }
        }
        
        return true;
        
        
    }
    
private:
    unordered_map<char,int> up;
    bool isValid33(vector<vector<char>>& board,int x, int y){
        up.clear();
        for(int i = x; i < x+3; i++){
            for(int j = y; j < y +3; j++){
                up[board[i][j]]++;
                if( board[i][j] !='.' && up[board[i][j]] > 1 )
                    return false;
            }
        }
        return true;
    }
};
image.png

所以这题 就是考 行, 列,3X3 在一个循环内的对应关系。
行转列很简单
主要是 行 转 3 X3
比如

(0,0), (0,1),(0,2) | (0,3),(0,4),(0,5)| (0,6),(0,7),(0,8) |
(1,0), (1,1),(0,2) | (1,3),(1,4),(1,5)| (1,6),(1,7),(1,8) |
.....
(3,0), (3,1),(3,2) | (3,3),(3,4),(3,5)| (3,6),(3,7),(3,8) |

我们希望在遍历行的同时,把 第一个3X3 映射到第0 个哈希表中, 第二个3x3映射到第二个哈希表中。。。以此类推
我们发现 i 增的比较慢(外循环)
i/3 的序列是

0,0,0,0,0,0,0,0,0,
......x 2
1,1,1,1,1,1,1,1,1,
......x 2
2,2,2,2,2,2,2,2,2
.......x 2

j增的比较快(内循环)
j/3 的序列是

0,0,0,1,1,1,2,2,2
0,0,0,1,1,1,2,2,2
0,0,0,1,1,1,2,2,2
.....x 6

我们想要的 序列是:

 0,0,0,1,1,1,2,2,2
...x 2
3,3,3,4,4,4,5,5,5
...x 2
6,6,6,7,7,7,8,8,8
..x 2

所以我们不难得出, i/3*3 + j/3 就是最终的 3x3 对应的哈希表编号

搞定 循环内 row,col, 3x3 的对应哈希表下标, 就可以把3个循环写在一起了。
这里因为只有9个数字(1..9), 所以我使用 比特位来做哈希数组,节省空间.

比特位作哈希数组,就是运用3个操作(<< , & ,|)
1<< k , 把 1 向左移动K位,
类似 hash_map[5] ==1
使用比特位就是 (00000001) << 5 == (00010000)
这样第5 个比特位就占上了,
如果再出现5 , 那么(00010000) & (00010000) 就会不等于0 。
反之, 就把该数字 | 到比特数组上, 把该比特位占上。

代码如下。

#include <vector>
using namespace std;
class Solution {
private:
   vector<int> row = vector<int>(9);
   vector<int> col =vector<int>(9);
   vector<int> sub  = vector<int>(9);
   int sub_index = 0;
   int bits;
public:
   bool isValidSudoku(vector<vector<char>>& board) {
       for(int i = 0;i < 9; i++){
           for(int j = 0; j < 9; j++){
               if(board[i][j] != '.'){
                   sub_index = i/3*3+ j/3;
                   // 使用 1个数字的不同比特位, 来当作一个哈希数组
                   bits = (1<< (board[i][j]-'0'));
                   if(row[i] & bits || col[j] & bits || sub[sub_index] & bits)
                       return false;// 有比特位被占, 说明有数字已经出现过
                       
                   // 没有出现过, 把该比特位占上
                   row[i] |=bits;
                   col[j] |=bits;
                   sub[sub_index] |=bits; 
               }     
           }
   } 
       return true;
   }
};
image.png

相关文章

  • Python小白 Leetcode刷题历程 No.36-N

    Python小白 Leetcode刷题历程 No.36-No.40 有效的数独、解数独、外观数列、组合...

  • Leetcode-36 有效的数独

    36. 有效的数独[https://leetcode-cn.com/problems/valid-sudoku/]...

  • DFS+回溯

    LeetCode 36 判断给出的数独是否有效https://www.cnblogs.com/ganganlove...

  • [leetcode] 36 有效数独

    leetcode 36 Determine if a 9x9 Sudoku board is valid. Onl...

  • 36. 有效的数独

    36. 有效的数独(难度:中等) 题目链接:https://leetcode-cn.com/problems/va...

  • 每天进步一点点【2019.8.24】

    一、有效的数独【leetcode 36】 题目描述:判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经...

  • LeetCode 36——有效的数独

    1. 题目 2. 解答 将数独中数字的 ASCII 码值转化到 0-8 之间作为散列值,建立一个散列表,然后分别逐...

  • [LeetCode]36、有效的数独

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

  • LeetCode: 36 有效的数独

    【记录性文章-数组】 代码思路:本质上还是判断数组内重复的题,所以还是使用一边判断是否在哈希表中,一边遍历向哈希表...

  • LeetCode - #36 有效的数独

    前言 我们社区陆续会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。微博:@故胤...

网友评论

      本文标题:[leetcode] 36 有效数独

      本文链接:https://www.haomeiwen.com/subject/spwezftx.html