【哈希】怎么用哈希表优化查找子数组问题-力扣930,560【超详细的算法教程】
说在前面
欢迎朋友们来到我的博客。
今天我们的重点是,哈希表。
哈希算法在某些题目里面可以很好的降低查找的时间复杂度,今天,博主就带来两道经典的题目,领着大家理解哈希,学会哈希!
当然,还想学习其它算法的朋友们,可以通过订阅博主的算法专栏,持续学习!
题目:
博主给大家的话
那么这里博主先安利一下一些干货满满的专栏啦!
数据结构专栏:手撕数据结构 这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
算法专栏:算法 这里可以说是博主的刷题历程,里面总结了一些经典的力扣上的题目,和算法实现的总结,对考试和竞赛都是很有帮助的!
力扣刷题专栏:跟着博主刷Leetcode 想要冲击ACM、蓝桥杯或者大学生程序设计竞赛的伙伴,这里面都是博主的刷题记录,希望对你们有帮助!
C的深度解剖专栏:C语言的深度解剖 想要深度学习C语言里面所蕴含的各种智慧,各种功能的底层实现的初学者们,相信这个专栏对你们会有帮助的!
OJ.930 和相同的二元子数组
题目描述和算法分析
思路和注意事项:
- 前缀和+差分+哈希查找
- 因为这里的数字仅仅只是
0/1
,而且个数有范围,所以我们直接用数组模拟哈希表即可,不会导致下标越界。
完整代码展示
class Solution {
public:
int numSubarraysWithSum(vector<int>& nums, int goal) {
int hash[60020] = { 0 };//哈希一定要记得初始化为0
int ans = 0;
//计算前缀和
for (int i = 1; i < nums.size(); i++) {
nums[i] += nums[i - 1];
//前缀和先算出来,这里可以原地调整,即调整过后nums[i]就是前面所有元素的和
//因为后面不用了,直接原地调整就行了
}
hash[goal] = 1;//把goal插入到哈希里面去
for (int i = 0; i < nums.size(); i++) {
//哈希:
ans += hash[nums[i]];
++hash[nums[i] + goal];
}
return ans;
}
};
OJ.560.和为 K 的子数组
题目描述和算法分析
思路和注意事项
- 乍一看这题和上一题貌似是完全一样的,但是我们要看,这一题的数字不再是
0/1
了,因此如果我们的哈希函数映射到哈希表上的时候可能会导致数组下标越界! - C++的STL中的
unordered_map
可以帮助我们完整大整数的映射。 - 所以这题其他都一样,把数组哈希换成STL的哈希就好了。
完整代码展示
class Solution {
private:
unordered_map<int, int>hash;
public:
int subarraySum(vector<int>& nums, int k) {
int ans = 0;
//其它的和上一题一样了
//其实前面的哈希表都可以用这个
for (int i = 1; i < nums.size(); i++) {
nums[i] += nums[i - 1];
}
hash.clear();
hash[k] = 1;
for (int i = 0; i < nums.size(); i++) {//这个要从头遍历哈希,从0开始
ans += hash[nums[i]];
++hash[nums[i] + k];
}
return ans;
}
};
尾声
相信看到这里,朋友们对于这两题的思路应该没啥问题了,博主在这篇文章里,没有给大家详细讲哈希的思路,但是通过做题,通过练习,我们可以了解哈希,并慢慢学会它们!
如果你感觉这篇博客对你有帮助的话,不要忘了一键三连哦!