代码随想录第五天 | 哈希表part01
哈希表理论基础
建议:大家要了解哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set 和map。
什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。 这句话很重要,大家在做哈希表题目都要思考这句话。
文章讲解:https://programmercarl.com/哈希表理论基础.html
242.有效的字母异位词
建议: 这道题目,大家可以感受到 数组 用来做哈希表 给我们带来的遍历之处。
题目链接/文章讲解/视频讲解: https://programmercarl.com/0242.有效的字母异位词.html
题目感想:
1.就是相同数量的字母来组成的不同的单词嘛,我们可以通过暴力循环来得出是否是异位词,也可以通过初始化一个数组,因为全是字母且小写,所以只用26位数组就行,然后先遍历第一个字符串,在数组其对应的位置上面+1,然后再遍历第二个字符串,在数组对应位置上-1,最后再检查整个数组,看是否有不为0的位,有则不是,没有则是异位字;
/**
* 242. 有效的字母异位词 字典解法
* 时间复杂度O(m+n) 空间复杂度O(1)
*/
class Solution {
public boolean isAnagram(String s, String t) {
int[] record = new int[26];
for (int i = 0; i < s.length(); i++) {
record[s.charAt(i) - 'a']++;
// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
}
for (int i = 0; i < t.length(); i++) {
record[t.charAt(i) - 'a']--;
}
for (int count: record) {
if (count != 0) {
// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
return false;
}
}
return true;
// record数组所有元素都为零0,说明字符串s和t是字母异位词
}
}
- 两个数组的交集
建议:本题就开始考虑 什么时候用set 什么时候用数组,本题其实是使用set的好题,但是后来力扣改了题目描述和 测试用例,添加了 0 <= nums1[i], nums2[i] <= 1000 条件,所以使用数组也可以了,不过建议大家忽略这个条件。 尝试去使用set。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0349.两个数组的交集.html
题目感想:
1.在有限定的范围的情况下,定义数组进行检索会更快,在不限制范围,我们需要考虑用set或者map,一个无序且不重复,一个有序允许重复;
2.最简单的思路就是,首先遍历第一个数组,将它的元素加入set,然后遍历第二个数组,并且去set中进行查找,如果能找到,那就将这个元素加入结果set,不能的话就直接下一个,最后将结果set转为数组输出,也可以直接申请一个结果数组进行存储;
import java.util.HashSet;
import java.util.Set;
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
return new int[0];
}
Set<Integer> set1 = new HashSet<>();
Set<Integer> resSet = new HashSet<>();
//遍历数组1
for (int i : nums1) {
set1.add(i);
}
//遍历数组2的过程中判断哈希表中是否存在该元素
for (int i : nums2) {
if (set1.contains(i)) {
resSet.add(i);
}
}
//方法1:将结果集合转为数组
return resSet.stream().mapToInt(x -> x).toArray();
//方法2:另外申请一个数组存放setRes中的元素,最后返回数组
int[] arr = new int[resSet.size()];
int j = 0;
for(int i : resSet){
arr[j++] = i;
}
return arr;
}
}
3.还有一种方法是,因为后面力扣给两个数组补充了长度限制,那我们可以直接定义两个数组,然后分别遍历这两个数组,比如说遍历到2,那么新定义的数组索引为2的数值+1;之后再定义一个数组,根据这两个数组中数值均不为0的索引存入结果数组
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
int[] hash1 = new int[1002];
int[] hash2 = new int[1002];
for(int i : nums1)
hash1[i]++;
for(int i : nums2)
hash2[i]++;
List<Integer> resList = new ArrayList<>();
for(int i = 0; i < 1002; i++)
if(hash1[i] > 0 && hash2[i] > 0)
resList.add(i);
int index = 0;
int res[] = new int[resList.size()];
for(int i : resList)
res[index++] = i;
return res;
}
}
- 快乐数
建议:这道题目也是set的应用,其实和上一题差不多,就是 套在快乐数一个壳子
题目链接/文章讲解:https://programmercarl.com/0202.快乐数.html
题目感想:
1.最简单的方法就是计算然后去set里面找是否出现过,没出现就存起来,直到结果为1或者出现重复的就结束;
class Solution {
public boolean isHappy(int n) {
Set<Integer> record = new HashSet<>();
while (n != 1 && !record.contains(n)) {
record.add(n);
n = getNextNumber(n);
}
return n == 1;
}
private int getNextNumber(int n) {
int res = 0;
while (n > 0) {
int temp = n % 10;
res += temp * temp;
n = n / 10;
}
return res;
}
}
2.还有一个方法就是用到了快慢指针,慢指针一次走一步,快指针一次走两步,之后比较他们的出的值是否有为1的或者他们的值是否相等,这样就不用存储了!!!是不是很熟悉,没错,我们在找链表中的环的时候也用到了这个,太有意思了。
class Solution {
public int getNext(int n) {
int totalSum = 0;
while (n > 0) {
int d = n % 10;
n = n / 10;
totalSum += d * d;
}
return totalSum;
}
public boolean isHappy(int n) {
int slowRunner = n;
int fastRunner = getNext(n);
while (fastRunner != 1 && slowRunner != fastRunner) {
slowRunner = getNext(slowRunner);
fastRunner = getNext(getNext(fastRunner));
}
return fastRunner == 1;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/happy-number/solutions/224894/kuai-le-shu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
3.还有一种是数学解法,这个就是找到一个三位数字可能会进入的循环链然后存起来,只要后面的计算的数字在这个循环链中那么就是不能为1的
class Solution {
private static Set<Integer> cycleMembers =
new HashSet<>(Arrays.asList(4, 16, 37, 58, 89, 145, 42, 20));
public int getNext(int n) {
int totalSum = 0;
while (n > 0) {
int d = n % 10;
n = n / 10;
totalSum += d * d;
}
return totalSum;
}
public boolean isHappy(int n) {
while (n != 1 && !cycleMembers.contains(n)) {
n = getNext(n);
}
return n == 1;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/happy-number/solutions/224894/kuai-le-shu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
感兴趣的可以去力扣看看详细的题解;
- 两数之和
建议:本题虽然是 力扣第一题,但是还是挺难的,也是 代码随想录中 数组,set之后,使用map解决哈希问题的第一题。
建议大家先看视频讲解,然后尝试自己写代码,在看文章讲解,加深印象。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0001.两数之和.html
题目感想:
1.简单的方法有两种,一种是在set中匹配自己需要的,匹配不到把自己加进去,然后循环;另外一种是,给这个数组排序,然后两个指针分布数组两端,根据和目标的大小进行缩进;
//使用哈希表
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
if(nums == null || nums.length == 0){
return res;
}
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
int temp = target - nums[i]; // 遍历当前元素,并在map中寻找是否有匹配的key
if(map.containsKey(temp)){
res[1] = i;
res[0] = map.get(temp);
break;
}
map.put(nums[i], i); // 如果没找到匹配对,就把访问过的元素和下标加入到map中
}
return res;
}
//使用哈希表方法2
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> indexMap = new HashMap<>();
for(int i = 0; i < nums.length; i++){
int balance = target - nums[i]; // 记录当前的目标值的余数
if(indexMap.containsKey(balance)){ // 查找当前的map中是否有满足要求的值
return new int []{i, indexMap.get(balance)}; // 如果有,返回目标值
} else{
indexMap.put(nums[i], i); // 如果没有,把访问过的元素和下标加入map中
}
}
return null;
}
//使用双指针
public int[] twoSum(int[] nums, int target) {
int m=0,n=0,k,board=0;
int[] res=new int[2];
int[] tmp1=new int[nums.length];
//备份原本下标的nums数组
System.arraycopy(nums,0,tmp1,0,nums.length);
//将nums排序
Arrays.sort(nums);
//双指针
for(int i=0,j=nums.length-1;i<j;){
if(nums[i]+nums[j]<target)
i++;
else if(nums[i]+nums[j]>target)
j--;
else if(nums[i]+nums[j]==target){
m=i;
n=j;
break;
}
}
//找到nums[m]在tmp1数组中的下标
for(k=0;k<nums.length;k++){
if(tmp1[k]==nums[m]){
res[0]=k;
break;
}
}
//找到nums[n]在tmp1数组中的下标
for(int i=0;i<nums.length;i++){
if(tmp1[i]==nums[n]&&i!=k)
res[1]=i;
}
return res;
}
代码随想录第五天 | 哈希表part01的更多相关文章
- 自己动手实现java数据结构(五)哈希表
1.哈希表介绍 前面我们已经介绍了许多类型的数据结构.在想要查询容器内特定元素时,有序向量使得我们能使用二分查找法进行精确的查询((O(logN)对数复杂度,很高效). 可人类总是不知满足,依然在寻求 ...
- Java基础知识笔记(一:修饰词、向量、哈希表)
一.Java语言的特点(养成经常查看Java在线帮助文档的习惯) (1)简单性:Java语言是在C和C++计算机语言的基础上进行简化和改进的一种新型计算机语言.它去掉了C和C++最难正确应用的指针和最 ...
- Java数据结构和算法之哈希表
五.哈希表 一般的线性表.树中,记录在结构中的相对位置是随机的即和记录的关键字之间不存在确定的关系,在结构中查找记录时需进行一系列和关键字的比较.这一类查找方法建立在“比较”的基础上,查找的效率与比较 ...
- SDUT 3377 数据结构实验之查找五:平方之哈希表
数据结构实验之查找五:平方之哈希表 Time Limit: 400MS Memory Limit: 65536KB Submit Statistic Problem Description 给定的一组 ...
- SDUT-3377_数据结构实验之查找五:平方之哈希表
数据结构实验之查找五:平方之哈希表 Time Limit: 400 ms Memory Limit: 65536 KiB Problem Description 给定的一组无重复数据的正整数,根据给定 ...
- ELF Format 笔记(十五)—— 符号哈希表
ilocker:关注 Android 安全(新手) QQ: 2597294287 符号哈希表用于支援符号表的访问,能够提高符号搜索速度. 下表用于解释该哈希表的组织,但该格式并不属于 ELF 规范. ...
- 数据结构 链式哈希表(Hash Table)的接口定义与实现分析(完整代码)
链式哈希表的接口定义 关于哈希表与链式哈希表的描述可以参阅:http://www.cnblogs.com/idreamo/p/7990860.html 链式哈希表的操作与属性有:初始化.销毁.插入元素 ...
- Java学习笔记31(集合框架五:set接口、哈希表的介绍)
set接口的特点: 1.不包含重复元素 2.set集合没有索引,只能用迭代器或增强for循环遍历 3.set的底层是map集合 方法和Collection的方法基本一样 set接口的实现类HashSe ...
- 左神算法第五节课:认识哈希函数和哈希表,设计RandomPool结构,布隆过滤器,一致性哈希,岛问题,并查集结构
认识哈希函数和哈希表 MD5Hash值的返回范围:0~9+a~f,是16位,故范围是0~16^16(2^64)-1, [Hash函数],又叫散列函数: Hash的性质: 1) 输入域无穷大: 2) ...
- perl5 第九章 关联数组/哈希表
第九章 关联数组/哈希表 by flamephoenix 一.数组变量的限制二.定义三.访问关联数组的元素四.增加元素五.创建关联数组六.从数组变量复制到关联数组七.元素的增删八.列出数组的索引和值九 ...
随机推荐
- redmine 迁移后邮箱配置
https://blog.csdn.net/love8753/article/details/126380927 步骤一 修改配置文件 步骤二 redmine 页面配置信息 步骤一 修改配置文件 打开 ...
- try except 案例
def to_split(df): # 删除不符合加班统计的记录 try: df.dropna(subset=['姓名'], inplace=True) hang_index = df[df['加班信 ...
- Cordova基本使用(一)
简述 Apache Cordova是一个开源的移动开发框架.允许你用标准的web技术-HTML5,CSS3和JavaScript做跨平台开发. 应用在每个平台的具体执行被封装了起来,并依靠符合标准的A ...
- 因为Apifox不支持离线,我果断选择了Apipost!
要说国内最有名的两款API开发工具不是Apipost就是Apifox,因为曾经遭遇到一件事,导致我坚定的选择了Apipost. 有一年春节我攒了足够的年假,提前开开心心的过年回家,路上我的领导给我打电 ...
- 小程序和APP抓包的问题
小程序和APP抓包的问题 很多同学都会遇到小程序和APP抓不到包的问题,抓不到https请求包,这边给大家提供一些解决方案. Yakit工具 首先需要的就是一个抓包神器yakit,这个工具非常好用强大 ...
- Netty基础—8.Netty实现私有协议栈
大纲 1.私有协议介绍 2.私有协议的通信模型 3.私有协议栈的消息定义 4.私有协议栈链路的建立 5.私有协议栈链路的关闭 6.私有协议栈的心跳机制 7.私有协议栈的重连机制 8.私有协议栈的重复登 ...
- PHP 读取csv中的指定某些列的值
封装一个方法,用于从CSV文件中读取指定的某些列的值时,可以使用以下示例代码: <?php class CSVReader { private $filename; private $delim ...
- nodejs队列
nodejs队列 创建具有指定并发性的队列对象.添加到队列的任务以并行方式处理(直到并发性限制).如果所有的worker都在进行中,任务就会排队,直到有一个worker可用.worker完成任务后,将 ...
- C# 工业视觉开发必刷20道 Halcon 面试题
前言 随着工业4.0的深入推进,越来越多的企业开始重视智能制造和自动化生产.在这个背景下,对具备C#和Halcon开发经验的专业人才需求也日益增长. 为了帮助广大 C#工业视觉开发的朋友更好地备战面试 ...
- VScode设置用户代码片段快捷方式
一.创建步骤 a. b. 二.创建模板 { "生成vue模板": { "prefix": "vue", "body": ...