力扣 36. 有效的数独 C语言实现

题目描述:

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

注意:

一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
空白格用 '.' 表示。

题目链接

 方法:创建三个 9*9 数组

本人感觉此题目较为难理解,前天看了这道题给搁置了,然后今天做了387. 字符串中的第一个唯一字符这道题才有了较为清晰的思路。 

首先创建三个 9* 9 的数组 cols, rows 和 tris 

首先初始化三个数组,令它们每一个元素的值都为0

cols 存放的是每行各个元素中出现的次数

比如实例1 中,board[0][0]='5', 由于board存放的数范围是1-9,那么在cols数组中令

cols[0][5-1]++ = cols[0][4]++,也就是在原来值的基础上加1. 由于board存的是字符类型,所以cols[0][5-1]的计算就是 cols[0][board[0][0]-'1'].

同样,board[1][1] = '6', 在cols数组中 cols[1][6-1]++ = cols[1][5]++ . 对于board中 '.' 的值略过。

同样,rows中,每行存的是 board 每列各元素出现的次数

实例1 中,board[3][0]='8',在rows数组中 rows[0][8-1]++ = rows[0][7]++ = rows[0][board[3][0]-'1'];

board[2][1]='9',在rows数组中 rows[1][9-1]++ = rows[1][8]++; 

下面重点来了,九宫格的计数~

由于一共有9个九宫格,从左到右,从上到下,依次标记每个九宫格索引值为0-2,3-5,6-8   如下图

那么在tris数组中,每行分别代表每个九宫格中元素出现的次数

故已知某个元素的行和列,怎么添加到tris数组的对应位置是一个需要解决的问题。

对于tris的列,我们只需要根据元素来获取即可,所以关键是寻找tris的行,也就是根据一个元素的行和列判断它是在哪个九宫格当中

每3个行位置和列位置更新一个九宫格,所以首先想到的肯定是除以3,如果让行 i/3 那对于第0个九宫格是可以的,而当i=3, 4, 5 时, i/3=1,那么第三个九宫格就不是3而是1. 所以需要再乘3. 也就是 i/3*3 能够准确的判断第0个,第3个和第6个九宫格。那么对于其他九宫格,我们就在列 j 上想办法。由于列也是每3个位置更新一个九宫格,故再让j/3,也就是  i/3*3+j/3  通过元素的行和列来验证此公式发现是可以的,这样我们就成功的解决了上面的问题。

将九宫格看成是 3*3 的数组,其中 i/3*3 代表的是九宫格行的位置。i/3 其实就是令每一个 i 处在第0、1、2三个位置,而九宫格不只有三行,还有三列,所以再乘3 令每个九宫格的行位置准确。而九宫格的列就是 j/3行+列就代表九宫格的位置。 

下面是代码展示

bool isValidSudoku(char** board, int boardSize, int* boardColSize){
    int rows[9][9];
    int cols[9][9];
    int tris[9][9];

    // 数组初始化 令每个元素都为0
    memset(rows, 0, sizeof(rows));
    memset(cols, 0, sizeof(cols));
    memset(tris, 0, sizeof(tris));
    
    // 将行、列和九宫格元素存在的个数分别存到三个数组中
    for(int i=0; i<9; ++i)
    {
        for(int j=0; j<9; ++j)
        {
            if(board[i][j]!='.')
            {
                int temp = board[i][j];
                
                rows[i][temp-'1']++;
                tris[i/3*3+j/3][temp-'1']++;
            }
            if(board[j][i]!='.')
            {
                int temp = board[j][i];
                cols[i][temp-'1']++;

            }
        }
    }
    
    // 判断 三个数组中是否有大于1的元素
    for(int i=0; i<9; ++i)
    {
        for(int j=0; j<9; ++j)
        {
            if(rows[i][j]>1 || cols[i][j]>1 || tris[i][j]>1)
            {
                return false;
            }
        }
    }
    
    return true;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值