哈希表是根据关键码的值而直接进行访问的数据结构。
直白来讲其实数组就是一张哈希表 - 哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素。
哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现集合里。
一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,也就找到对应hash表中的index。
两个元素的hash函数指向hash表中相同的位置。
注意:其实拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间。
依靠哈希表中的空位来解决碰撞问题 >> 一定要保证tableSize大于dataSize
例如冲突的位置,放了小李,那么就向下找一个空位放置小王的信息。所以要求tableSize一定要大于dataSize ,要不然哈希表上就没有空置的位置来存放 冲突的数据了。
题目:力扣
第一反应是采用Hashmap进行储存s中的字母出现的频率,然后储存t中的出现频率进行对比,但是这样其实和暴力解法有点像。
参考了其他解法,可以把t中出现的字母在储存s的map中进行搜索,然后-1,这样如果相同的情况下,那肯定是最后为0的,不相同的话,这个字母在map中的出现频率肯定<0。
这样实现之后仍然没有全部通过,"ab","a"这样的例子测试为true。
然后发现还需要一个前提条件 - 字符串必须是长度相等的。
public boolean isAnagram(String s, String t) {
if(s.length() != t.length()){
return false;
}
HashMap map = new HashMap<>();
for(int i=0; i
其他解法:
对s和t中的字符进行排序,然后判断两个字符串是否相等,如果不相等则为false
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
char[] str1 = s.toCharArray();
char[] str2 = t.toCharArray();
Arrays.sort(str1);
Arrays.sort(str2);
return Arrays.equals(str1, str2);
}
}
该题中的用例只有小写字母,类似hashmap的做法,创建一个长度为26的数组代表从a-z的字母,使用
s.charAt(i) - 'a'
计算出字符在数组中的位置,然后+1;而对于t则是计算出字符在数组中的位置,然后-1。
若有字符的频率<0, 则为false。
也需要注意前提,两个字符的长度必须相等。
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
int[] table = new int[26];
for (int i = 0; i < s.length(); i++) {
table[s.charAt(i) - 'a']++;
}
for (int i = 0; i < t.length(); i++) {
table[t.charAt(i) - 'a']--;
if (table[t.charAt(i) - 'a'] < 0) {
return false;
}
}
return true;
}
}
参考资料:
力扣 ,代码随想录
采用两个集合 - 一个集合储存set1的元素,一个集合储存set1中包含set2的元素 - 将set转化成数组。
这里注意代码的简洁 - 使用Stream进行set到数组的转换
public int[] intersection(int[] nums1, int[] nums2) {
if(nums1 == null || nums1.length == 0 ||nums2 == null || nums2.length == 0){
return new int[0];
}
HashSet set1 = new HashSet<>();
for(int i=0; i set2 = new HashSet<>();
for(int i=0; i x).toArray();
}
题目:力扣
这道题主要是理解题意:可能会无限循环不能到1;可能会到1
无限循环说明重复
因此判断循环终止的条件是 是否到1 或者是否有重复 --> 使用集合
在实现的时候对于循环条件判断有些问题
对于取n的每个位的数,开始循环采用
while(n/10>0)
但是发现在对个位数进行判断的时候 - n/10是直接等于0的也就跳过了
因此循环条件改为
while(n!= 0 && n/10 >= 0)
其实是等同于可以直接用 n>0这个条件的
所以整体代码为
class Solution {
HashSet set = new HashSet<>();//set储存n
public boolean isHappy(int n) {
while(n != 1 && !set.contains(n)){//如果n不在set中(没有循环),不等于1
set.add(n);//n加入set中
int sum =0;
while(n>0){
int x = n%10;//取高位数
sum = sum + x*x;//累加
n = n/10;//去掉最高位
}
n = sum;// 替换n
}
return n==1; //判断n是否等于1
}
}
参考资料:
代码随想录
题目:力扣
这道题其实如果直接使用暴力的话很容易解决。
但是在找target是否为数组中的两个数的和时;已知数组中的一个数A,那么B是能够求出来的
--> B=target -A
需要判断B是否在这个数组中,并且得知B的index
那么判断一个元素是否在一个集合中 - 可以采用Hash表的方法
这里因为还需要得知B的index,因此同时需要储存B以及B的index -- hashmap时最合适的
在遍历的时候,把元素以及元素的index放入map,同时判断map中是否存在B。若是存在则直接返回这两个下标。
这样只需要O(1)的时间就可以得到结果。 - 最多扫描一遍
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap map = new HashMap<>();
for(int i=0; i