没有合适的资源?快使用搜索试试~ 我知道了~
资源详情
资源评论
资源推荐
**
🍭
更多精彩内容,欢迎关注:公众号 / Github / LeetCode / 知乎 **
噔噔噔噔,这是公众号「噔噔噔噔,这是公众号「宫水三叶的刷宫水三叶的刷题题日日记记」的原」的原创专题创专题「哈希表」合集。「哈希表」合集。
本合集更新时间本合集更新时间为为 2021-10-07,大概每,大概每 2-4 周会集中更新一次。周会集中更新一次。关注公众号,后台回复「哈希注公众号,后台回复「哈希
表」即可获取最新下表」即可获取最新下载链载链接。接。
💡💡
下面介下面介绍绍使用本合集的最佳使用实使用本合集的最佳使用实践::
学学习习算法:算法:
1. 打开在线目录(Github 版 & Gitee 版);
2. 从侧边栏的类别目录找到「哈希表」;
3. 按照「推荐指数」从大到小进行刷题,「推荐指数」相同,则按照「难度」从易到
难进行刷题‘
4. 拿到题号之后,回到本合集进行检索。
维维持熟持熟练练度:度:
1. 按照本合集「从上往下」进行刷题。
学学习习过程中遇到任何困过程中遇到任何困难难,欢迎加入「每日一,欢迎加入「每日一题题打卡打卡 QQ 群:群:703311589」」进进行交流行交流
🍭🍭🍭🍭🍭🍭
**
🍭
更多精彩内容,欢迎关注:公众号 / Github / LeetCode / 知乎 **
题题目描述目描述
这是 LeetCode 上的 1. 两数之和两数之和 ,难度为 简简单单。
Tag : 「哈希表」、「模拟」
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出「和为目标值」的那
「两个」整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
• 2 <= nums.length <= 10
3
• -10
9
<= nums[i] <= 10
9
• -10
9
<= target <= 10
9
• 只会存在一个有效答案
朴素解法朴素解法
由于我们每次要从数组中找两个数。
因此一个很简单的思路是:使用两重循环枚举下标 i 和 j ,分别代表要找的两个数。
然后判断 nums[i] + nums[j] == target 是否成立。
另外为了防止得到重复的解,我们需要在第一层循环中让 i 从 0 开始,到 n - 2 结束(确保能取
到下一位数作为 j );在第二层循环中让 j 从 i + 1 开始,到 n - 1 结束。
class Solution {
public int[] twoSum(int[] nums, int t) {
int n = nums.length;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (t == nums[i] + nums[j]) return new int[]{i,j};
}
}
return new int[]{};
}
}
* 时间复杂度:两重循环,以复杂度是 O(n
2
)
* 空间复杂度:O(1)
哈希表解法哈希表解法
首先,任何优化的思路都不外乎「减少重复」。
从朴素解法中可以知道,逻辑上我们是先定下来一个数,然后从数组中往后找另外一个值是否存
在。但其实我们在找第二个数的过程中是重复扫描了数组多次。
举个例子,对于 nums = [2,3,8,4], target = 9 的样例,我们先确定下来第一个数是 2 ,
然后从后扫描到最后一个数,检查是否有 7 。发现没有,再决策第一个数为 3 的情况,这时
候我们应该利用前一次扫描的结果来帮助我们快速判断是否存在 6 ,而不是再重新进行一次扫
描。
这是直观的优化思路,不难想到可以使用哈希表进行存储。以数值为 key,数值的下标
为 value。
当动手将想法转化为代码时,会发现如果先敲定第一个数,将后面的数加入哈希表,再进行下一
位的遍历的时候,还需要将该数值从哈希表中进行删除。
class Solution {
public int[] twoSum(int[] nums, int t) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) map.put(nums[i], i);
for (int i = 0; i < nums.length; i++) {
int a = nums[i], b = t - a;
if (map.get(a) == i) map.remove(a);
if (map.containsKey(b)) return new int[]{i, map.get(b)};
}
return new int[]{};
}
}
最坏情况下,每个数会对应一次哈希表的插入和删除。该解法本质是在循环过程中敲定第一个
数,在哈希表中找该数后面是否存在第二个数。
这时候不妨将思路转换过来,遍历过程中敲定第二个数,使用哈希表在第二个数的前面去找第一
个数。
具体的做法是,边遍历边存入哈希表,遍历过程中使用的下标 i 用作敲定第二个数,再从现有的
哈希表中去找另外一个目标数(由于下标 i 前面的数都被加入哈希表了,即在下标 i 前面去找第
一个数)。
class Solution {
public int[] twoSum(int[] nums, int t) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int a = nums[i], b = t - a;
if (map.containsKey(b)) return new int[]{map.get(b), i};
map.put(a, i);
}
return new int[]{};
}
}
从 LeetCode 上的执行时间来看,第一种哈希表做法是 4ms,而第二种哈希表的做法
是 0ms(不足 1ms 的意思),快在了我们减少了哈希表的插入和删除操作。
但这只是常数级别上的优化,LeetCode 上的执行时间建议只作普通参考,还是要从算法的时空
复杂度来分析快慢。
* 时间复杂度:第一种哈希表的做法会扫描数组两次,复杂度是 O(n)(忽略常数);第二种做
剩余166页未读,继续阅读
啊看看
- 粉丝: 28
- 资源: 323
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0