一、哈希表理论基础
- 哈希表解决的问题:一般哈希表都是用来快速判断一个元素是否出现集合里
- 本质是用空间换时间,因为还要使用数组,set,map来保存 原值和hash值的对应关系
- 哈希函数
- 案例:将学生姓名投射成哈希表上的索引,进而快速判断表中是否存在该学生
- 如果hash值大于tableSize怎么办?取模
- 如果学生数量大于tableSize怎么办?(两个学生名投射到哈希表同一位置上)哈希碰撞就引出来了
- 如何解决哈希碰撞?拉链法和线性探测法
-
拉链法,在冲突位置在保存一个链表
-
线性探测法
- 前提条件:保证tableSize 大于 dataSize
- 小王和小李冲突了,那么就向下寻找空位放置小王
-
二、有效的字母异位词
class Solution {
public boolean isAnagram(String s, String t) {
//如果 两字符串长度不相等,那么一定不是字母异位词
if (s.length()!= t.length()) return false;
HashMap<Character, Integer> dic = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
// 这一行是向 map中 key为 s.charAt(i) 的对应 value + 1
dic.put(s.charAt(i) , dic.getOrDefault(s.charAt(i), 0) + 1);
// 这一行是向 map中 key为 s.charAt(i) 的对应 value - 1
dic.put(t.charAt(i) , dic.getOrDefault(t.charAt(i), 0) - 1);
}
//如果两个字符串中字符组成相等,那么最后map中所有数据的value值都为0,不为0则表示s t 不是字母异位词
for (int val : dic.values()) {
if (val != 0)
return false;
}
return true;
}
}
三、两个数组的交集
假设有数组1,2
-
两个集合 Set1,Set2,遍历其中一个数组加入到set1中
-
在遍历另外一个数组时判断set中是否存在该数
-
如果存在,则添加到set2中
-
再以set大小创建一个新数组,遍历set加入到数组中返回即可
- 注意set无法用索引遍历
-
//给定两个数组 nums1 和 nums2 ,返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 // // // // 示例 1: // // //输入:nums1 = [1,2,2,1], nums2 = [2,2] //输出:[2] // // // 示例 2: // // //输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] //输出:[9,4] //解释:[4,9] 也是可通过的 // // // // // 提示: // // // 1 <= nums1.length, nums2.length <= 1000 // 0 <= nums1[i], nums2[i] <= 1000 // // // Related Topics 数组 哈希表 双指针 二分查找 排序 👍 899 👎 0 //leetcode submit region begin(Prohibit modification and deletion) class Solution { public int[] intersection(int[] nums1, int[] nums2) { if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) { return new int[0]; //长度为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; } }
四、快乐数
有些许类似之前环形链表二那道题,这里用的是“隐形环”,当计算过程中同一个数字出现两次时,由于每一次数字迭代的计算逻辑相同,那么这个数是不会达到 “1”,也就不是快乐数
计算快乐数逻辑,每次提取出个位,然后总体除以 10 去除 个位,不断遍历计算
while(n > 0){
int d = n % 10;
n = n / 10;
totalSum += d*d;
}
五、两数之和
-
创建一个HashMap,用来保存已遍历完成但暂时没有找到存在两数和为target的数字
- 比如 target为 10 ,nums[2,4,5,8,…],先保存2,因为还没有遍历到8,8没有存到map中
- key对应数组中索引,值为数组中的值,
数之和
-
创建一个HashMap,用来保存已遍历完成但暂时没有找到存在两数和为target的数字
- 比如 target为 10 ,nums[2,4,5,8,…],先保存2,因为还没有遍历到8,8没有存到map中
- key对应数组中索引,值为数组中的值,
-
进行for循环,如果map中存在 target - num[i],则返回当前索引和target - num[i]对应索引