初级算法题->有效的数独--弄清哈希表的本质

题目

判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次

示例

输入:
[
[“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”]
]
输出: true

解法一:三个二维数组实现

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
//利用数组作为哈希表时,由于需要多个哈希表来判断不同行列格子中数字的出现次数
//故我们可以利用一个二维数组来实现,每行或每列都用新二维数组中的行标表示,
//而新二维数组的每行我们将其视为对原数独不同行或列的哈希表,
//而用每行的a[][0~8]分别表示数字1~9的出现次数,遍历数字得到次数1,
//若之后再继续遍历数字次数不为0,则数字重复不满足数独要求。
        //那么如何用于表述每个网格的出现次数呢?网格同样有9个,同样可通过对网格编号实现数组化哈希表
        //让k=i/3*3+j/3得到网格编号,其中i和j代表数独的行和列
//同时大家还要注意数组从0下标开始所以作为哈希表key-value映射的时候需要让key-1.
vector<vector<int>>row(9,vector<int>(9,0));
vector<vector<int>>column(9,vector<int>(9,0));
vector<vector<int>>grid(9,vector<int>(9,0));
for(int i=0;i<9;i++){
    for(int j=0;j<9;j++){
        if(board[i][j]=='.')
        continue;
        int value = board[i][j]-'0'-1;
        int k=i/3*3+j/3;
        if(row[i][value]!=0||column[j][value]!=0||grid[k][value]!=0)
            return false;
        row[i][value]=column[j][value]=grid[k][value]=1;
    }
}
return true;
    }
};

效率一般在这里插入图片描述

解法二:三个一维数组利用单个位存储实现

注意用位存储实现哈希表的key-value,只能实现1~64个数字的存储,即记录该数字对应位然后赋值为1,例如9就可以表示为1<<9得到1000000000,即在某个位占个1便标记该数字出现过。这就是位运算作哈希表的原理,很明显只适合用于记录出现一次的情况

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        int row[9] = {0};//均表示9行9列9格,其中每个元素的位用于标记出现过的数字
        int column[9] = {0};
        int grid[9] = {0};
        int shift = 0;
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                if(board[i][j]=='.')
                    continue;
                int value = board[i][j]-'0';
                int k = i/3*3+j/3;
                shift = 1<<value;
        //若出现过,则按位与结果应为原数,若要是没出现过则结果均为0,故可以用!0或者==value来判断
        //注意运算的优先级,小括号一定得带上!!!
                if((row[i]&shift)!=0 || (column[j]&shift)>0 || (grid[k]&shift)!=0)
                    return false;
                row[i] |= shift;
                column[j] |= shift;
                grid[k] |= shift;
            }
        }
        return true;
    }
};

效率提升了不少啊
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]中提到了哈希表的正向迭代器的实现,其中包括存储哈希表地址的成员变量。引用\[2\]中提到了哈希表的析构函数的实现,其中释放了哈希表中的结点。引用\[3\]中提到了哈希表的拷贝构造函数的实现,其中进行了深拷贝操作。根据这些信息,我们可以得出哈希表的一些特点和功能。 首先,哈希表是一种数据结构,用于存储键值对。它通过哈希函数将键映射到桶中,并将值存储在对应的桶中。哈希表的实现通常使用数组来表示桶,每个桶中存储一个链表或红黑树来解决哈希冲突。 哈希表的正向迭代器是对哈希结点指针的封装,其中存储了哈希表的地址。通过迭代器,我们可以遍历哈希表中的键值对。 哈希表的析构函数用于释放哈希表中的结点。它遍历哈希表的每个桶,释放桶中的结点,并将桶置为空。 哈希表的拷贝构造函数实现了深拷贝操作。它将源哈希表的大小调整为目标哈希表的大小,然后将源哈希表中的每个桶中的结点一个个拷贝到目标哈希表中,并更新目标哈希表有效数据个数。 综上所述,哈希表是一种用于存储键值对的数据结构,它提供了正向迭代器、析构函数和拷贝构造函数等功能。 #### 引用[.reference_title] - *1* *2* *3* [C++ STL(九) -------- 哈希表封装unordered_map和unordered_set](https://blog.csdn.net/m0_52169086/article/details/126709111)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值