Day6
前言
开始补了,不一定是一天完成的
文章:代码随想录
LeetCode 242 有效的字母异位词
自己思路
大概懂了哈希的原理,但是不太会用代码实现,先看视频吧
看完讲解
没想到是直接一个数组就能实现了,牢记数组就是一个简单哈希表,当哈希值不大的时候用数组是很方便的。卡哥讲完之后感觉思路很清晰了,就是用一个26位的数组来标识s字母出现的频率,然后再去遍历t的时候,就在对应字母数组索引位置进行--,最后判断26位数组是不是每一位都为0就行。其中巧妙点在于不需要刻意去记ASCII码,将每个字母-'a',运算出来就是数组的索引值0~25,很妙
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']++;
}
for (int i = 0; i < t.length(); i++) {
record[t.charAt(i) - 'a']--;
}
for (int i = 0; i < record.length; i++) {
if(record[i] != 0){
return false;
}
}
return true;
}
}
LeetCode 349 两个数组的交集
自己思路
感觉有个大概的思路,但应该不是数组可以解决的问题,不会写
看完讲解
这道题的关键就是采用HashSet来解决,当哈希值数量多或者未知,或哈希值分散且跨度大的时候,数组将不再适合解决哈希问题,此时就可以考虑使用HashSet。这里使用HashSet还有一个好处,因为需要返回无重复的交集,HashSet具有自动去重功能完美适配。
在一开始的时候可以对数组为空(没有被初始化)或者长度为0(已经被初始化但不包含任何元素)进行一个判断,如果是这样可以直接返回一个长度为0 的数组。后面可以对nums1进行处理,将其转化为hashset,再对nums2进行处理,遍历nums2去hashset里面查看是否包含,包含的话就填入交集set中,即完成了题目要求。最后的话注意需要返回数组,我这里重新new一个数组,再采用遍历set依次填入新数组进行返回,也可以直接进行格式转换去返回(还不懂这个)
set.stream().mapToInt(x -> x).toArray();
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> hashSet1 = new HashSet<>();
for (int i = 0; i < nums1.length; i++) {
hashSet1.add(nums1[i]);
}
Set<Integer> commonHashSet = new HashSet<>();
for (int i = 0; i < nums2.length; i++) {
if (hashSet1.contains(nums2[i])) {
commonHashSet.add(nums2[i]);
}
}
int[] arr = new int[commonHashSet.size()];
int j = 0;
for (Integer e : commonHashSet) {
arr[j] = e;
j++;
}
return arr;
}
}
LeetCode 202 快乐数
自己思路
感觉思路还挺混乱的,有递归的感觉,而且好像也没办法确认到底是几位数,每次都先求一下有几位数吗?
看完讲解
直接看着答案去写的,发现思路没有想的那么难,上面说到的问题其实可以再用一个函数去求取下一个n就能解决。这道题的关键还是采用HashSet来解决,定义一个hashset来存储每次的平方和,每传入一个数,先判断是否为1(直接就是快乐数)以及是否在hashset中存在(存在就说明平方和循环了,不可能是快乐数),然后返回n==1的结果就可以确认是不是快乐数(匹配了前面两个判断条件)。如果可以进入循环,就不断地循环向hashset中添加值,并构建一个函数去获取下一个n,不断地对n进行%10和/10,只要n大于0就一直进行,并将平方和结果返回,循此往复,其实写完感觉思路还是能理解的
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;
}
}
LeetCode 1 两数之和
自己思路
没有思路,看答案
看完讲解
首先本题也是用哈希表来解决,因为相当于遍历数组的时候,每遇到一个值,就去查找target减去它我们是否已经遍历过,即遇到了需要快速判断一个元素是否出现集合里,非常适配哈希法。此处使用的是HashMap,因为我们不仅仅需要存值,还需要存储索引,类似于Key-Value,所以采用map结构。这里的map,就是用来存储已经遍历过的元素的,需要注意,key存的是值,value存的是索引,因为我们是去查找某个值是否遍历过(所以作为key去查找),要返回的也是数组索引(所以作为value去存储),而且当数组多个索引位置是同一个值的时候,由于map的key的唯一性,也可以避免重复存储(会覆盖)。
代码其实就比较简单了,上来先定义个2位的数组,作为返回,如果nums数组为null或者长度为0就可以直接返回初始化的数组。后面就可以定义一个HashMap来存储遍历过的元素,遍历数组,每遍历一位就去map里面查找相加可以等于target的值,如果有,就直接将该key的value和当前位的索引存入数组返回,否则就不断将遍历的数字存入map中,如果一直未匹配上,那么返回的还是初始化的数组。
class Solution {
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];
if (map.containsKey(temp)) {
res[0] = map.get(temp);
res[1] = i;
break;
}
map.put(nums[i], i);
}
return res;
}
}
总结
用时:5.5h
断更很久,重新开始,哈希表没想象的那么难,虽然基本没有自己手撕出来的哈哈
HashSet的定义和操作
HashSet不允许集合中有重复的元素(自动去重)
// HashSet的定义
Set<Integer> set = new HashSet<>();
// 添加元素
set.add(element);
// 移除元素
set.remove(element);
// 检查集合是否包含某个元素
set.contains(element);
// 检查集合是否为空
set.isEmpty();
// 获取集合中元素的数量
set.size();
// 清空集合
set.clear();
// 遍历HashSet
for (Integer element : set) {
System.out.println("Element = " + element);
}
HashMap的定义和操作
// HashMap的定义 键:Key(唯一) 值:Value
Map<Integer,Integer> map = new HashMap<>();
// 将指定的Key和Value添加到此映射
map.put(key, value);
// 返回指定Key所映射的Value
map.get(key);
// 返回指定Key所映射的Value,否则返回defaultValue
map.getOrDefault(Object key, V defaultValue)
// 从该映射中移除Key的映射
map.remove(key);
// 此映射是否包含指定Key的映射
map.containsKey(key);
// 返回此映射中的Key-Value映射关系数
map.size();
// 此映射空否
map.isEmpty();
// 遍历Map
// map.entrySet()用于返回Map中的所有键值对(Key-Value pair)的集合
// Map.Entry是Map的一个内部接口,表示Map集合中的一个实体(即一个键值对)
// entry.getKey()获取该键值对的键
// entry.getValue()获取该键值对的值
for (Map.Entry<Integer,Integer> entry : map.entrySet()){
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}