代码随想录算法训练营第六天 | LeetCode242 有效的字母异位词、LeetCode 349 两个数组的交集、LeetCode 202 快乐数、 LeetCode 1. 两数之和
)
哈希表就是通过将作为key的值通过hash运算转换成数组的下标, 然后再在对应下标处传入 key-value键值对
如果多个key经过hash运算之后的下标值一样, 称之为hash碰撞
为了避免hash碰撞, 我们可以让数组 存储的值为链表头, 这样如果发生hash碰撞, 就在对应的链表尾加上对应的 key-value键值对
今天知道的解决办法有两种
- 拉链法: 发生hash冲突的值存储在链表中,就是存储元素的数组存储的是链表头, 如果发生hash碰撞, 就在对应的链表尾加上键值对
- 线性探测法: 使用线性探测法,一定要保证数组大小要大于要存储的元素个数。如果发生了冲突:就从发生冲突的位置向下寻找一个空位来存储对应值
常见哈希结构
- 数组: 数组可以看成key是下标, hash运算为没有操作(可以跟数学种的不变化也是变化的一种联系理解), 而value就是要存储的元素值(存储的不是键值对哟)
- hashMap: 存储元素的是数组, 但数组存储的是链表头, 而链表的结构就是键值对(大概
- hashSet: 跟hashMap差不多, 存储的也是key-value键值对, hashSet的存储是用hashMap来完成的,每次存储时调用的方法为
return map.put(e, PRESENT)==null;
PRESENT是个固定值, 也就是说每次存储的值是在key属性里面的, 这也就是为什么hashSet不能存储相同值了吧(如果按照这样的说的话,多次添加的相同的值, 在hashMap里找到的也是相同的键值对, 不会做任何的操作。
注意:hashMap和hashSet的存储元素的顺序是无序的,遍历也是无序的
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法
LeetCode242 有效的字母异位词
题目链接
这道题限制了组成字符串的字母均为小写字母, 又因为在ASCII表中,小写字母都是挨着的, 故可以使用数组
public boolean isAnagram(String s, String t) {
int[] res = new int[26];
for(int i = 0 ; i < s.length(); i++){
res[s.charAt(i)-'a']++;
}
for(int i = 0; i <t.length(); i ++){
res[t.charAt(i)-'a']--;
}
for(int i = 0 ; i < res.length; i++){
if(res[i] != 0){
return false;
}
}
return true;
}
也可以使用hashMap
public boolean isAnagram(String s, String t) {
HashMap<Character, Integer> myHash = new HashMap<>();
for(int i = 0; i< s.length(); i++){
char temp = s.charAt(i);
if(myHash.containsKey(temp)){
myHash.replace(temp, myHash.get(temp)+1);
}else{
myHash.put(temp,1);
}
}
for(int i = 0; i < t.length(); i++){
char temp = t.charAt(i);
if(myHash.containsKey(temp)){
myHash.replace(temp, myHash.get(temp)-1);
}else{
return false;
}
}
for(int value : myHash.values()){
if(value != 0){
return false;
}
}
return true;
}
LeetCode 349 两个数组的交集
题目链接
使用hashSet
这是照着官方解法打的, 不愧是官方
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> mySet1 = new HashSet<>();
Set<Integer> mySet2 = new HashSet<>();
for(int num : nums1){
mySet1.add(num);
}
for(int num : nums2){
mySet2.add(num);
}
return getIntersection(mySet1, mySet2);
}
public int[] getIntersection(Set<Integer> mySet1, Set<Integer> mySet2) {
if(mySet1.size() > mySet2.size()){
return getIntersection(mySet2, mySet1);
}
Set<Integer> intersectionSet = new HashSet<>();
for(int num : mySet1){
if(mySet2.contains(num)) {
intersectionSet.add(num);
}
}
int[] intersection = new int[intersectionSet.size()];
int index = 0;
for(int num : intersectionSet){
intersection[index++] = num;
}
return intersection;
}
因为题目说了元素最大值为1000, 故也可以使用数组
public int[] intersection(int[] nums1, int[] nums2) {
int[] arraySet = new int[1001];
int[] res = new int[Math.max(nums1.length, nums2.length)];
int index = 0;
int size = 0;
for(int i = 0; i < nums1.length; i++){
int temp = nums1[i];
if(arraySet[temp] == 0){
arraySet[temp]++;
}
}
for(int i =0; i < nums2.length; i++){
int temp = nums2[i];
if(arraySet[temp] ==1){
arraySet[temp] -= 2;
}
}
for(int i = 0; i < arraySet.length; i++){
if(arraySet[i] == -1){
res[index++] = i;
size++;
}
}
return Arrays.copyOf(res,size);
}
LeetCode 202 快乐数
public boolean isHappy(int n) {
Set<Integer> mySet = new HashSet<>();
while(n != 1 ){
int temp = 0;
int sum = 0;
while(n !=0){
temp = n % 10;
n = n / 10;
sum += temp * temp;
}
n = sum;
if(mySet.contains(sum)){
break;
}else{
mySet.add(sum);
}
}
return n == 1;
}
LeetCode 1. 两数之和
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> myHash = new HashMap<>();
for(int i = 0; i < nums.length; i++){
if( myHash.containsKey(target-nums[i])){
return new int[]{myHash.get(target-nums[i]), i};
}else{
myHash.put(nums[i], i);
}
}
return new int[]{};
// 或者返回 return new int[0]
}
今日总结:
用心去感受, 用心去理解, 用心去爱