哈希表理论基础
哈希表
哈希表也叫散列表,数组就是哈希表。
哈希表可以用来快速判断一个元素是否在集合中。
哈希函数
哈希函数的作用就是把元素映射到哈希表的索引中,通过索引可以实现快速查找。
在映射的过程中往往会出现把多个元素映射到同一个索引的情况,称为哈希碰撞。哈希碰撞有两种解决方法
- 拉链法
- 拉链法的核心思想是把产生哈希碰撞的元素串起来,存在链表中。
- 线性探测法
- 线性探测法则是要给产生哈希碰撞的元素重新映射,直到碰撞消失为止。因此一定要保证tableSize大于dataSize。
哈希结构
常见的哈希结构有数组、map和set
242.有效的字母异位词
已完成
思路:
本题需要统计字符串中每个字母的数量,由于字母总共只有26个,因此可以定义长度为26的数组来统计数量。
过程中并不需要直到每个字母的ASCII码,只需要知道与a的差值即可。
代码
class Solution {
public boolean isAnagram(String s, String t) {
if(s.length() != t.length()) return false;
int[] sCount = new int[26];
int[] tCount = new int[26];
for(int i=0;i<s.length();i++){
sCount[s.charAt(i)-'a']++;
}
for(int i=0;i<t.length();i++){
tCount[t.charAt(i)-'a']++;
}
for(int i=0;i<sCount.length;i++){
if(sCount[i]!=tCount[i]) return false;
}
return true;
}
}
349. 两个数组的交集
已完成
思路:
本题需要多次去重,第一时间想到set
最后set
转为int[]
搜了一下:res.stream().mapToInt(x->x).toArray()
代码
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> res = new HashSet();
Set<Integer> set1 = new HashSet();
// nums1 去重,得到set1
for(int value : nums1){
set1.add(value);
}
// 遍历nums2,取出公共部分添加到结果集
for(int value : nums2){
if(set1.contains(value)){
res.add(value);
}
}
return res.stream().mapToInt(x->x).toArray();
}
}
202. 快乐数
已完成
思路:
第一想法是这道题如果在比赛里可以用查表做。。。
一开始没想到sum会重复出现,用暴力法也能过。
代码
class Solution {
// 暴力解法
public int[] split(int n){
// 将int拆分为数组
Integer N = Integer.valueOf(n);
String tempN = N.toString();
int[] num = new int[tempN.length()];
for(int i=0;i<tempN.length();i++){
Character ch = tempN.charAt(i);
num[i]=Integer.parseInt(ch.toString());
}
return num;
}
public boolean isHappy(int n) {
int sum = n;
for(int i=0;i<10000;i++){
int[] num = split(sum);
// 这里要先把sum清空
sum=0;
for(int val : num){
sum+=val*val;
}
if(sum==1) return true;
}
return false;
}
}
判断和是否循环出现的解法
class Solution {
public int getNextSum(int n){
int res = 0;
while(n>0){
int val = n%10;
res += val*val;
n /= 10;
}
return res;
}
public boolean isHappy(int n) {
Set<Integer> set = new HashSet();
int sum = n;
while(true){
if(sum==1) return true;
// 和重复出现,直接return false
if(set.contains(sum)) return false;
set.add(sum);
sum = getNextSum(sum);
}
}
}
1. 两数之和
已完成
思路:
哈希表的作用是快速判断一个元素是否在集合中,顺着这个往下想
先遍历一遍数组,对于遍历出的每个元素,如果符合条件的另一个数target-nums[i]
也存在数组中且不是同一个元素,条件即可满足
代码
class Solution {
public static ArrayList findIndex(int[] array, int target) {
// 返回数组中所有target的下标
ArrayList<Integer> res = new ArrayList();
for (int i = 0; i < array.length; i++) {
if (array[i] == target) {
res.add(i);
}
}
return res;
}
public int[] twoSum(int[] nums, int target) {
int i;
ArrayList<Integer> array = new ArrayList();
// 遍历数组
for(i=0;i<nums.length;i++){
int minus = target - nums[i];
// 找到目标元素在数组中的全部位置
array = findIndex(nums,minus);
if(array.size()>0){
if(minus!=nums[i]) return new int[]{i,array.get(0)};
else{
if(array.size()>1){
int res = array.get(0) == i?array.get(1):array.get(0);
return new int[]{i,res};
}
}
}
}
return new int[]{-1,-1};
}
}
上面的代码比较繁琐,可以使用map记录下索引位置
这里要注意map中key和value的存储值,key存放元素,value存放元素的索引
因为我们实际需要查询的是元素的索引
class Solution {
public int[] twoSum(int[] nums, int target) {
// 元素,下标
Map<Integer,Integer> map = new HashMap<>();
for(int i =0;i<nums.length;i++){
// 目标元素
int val = target - nums[i];
// 判断目标元素是否在集合中
// 由于题目保证有唯一解,可以直接return该解
if(map.containsKey(val)) return new int[]{i,map.get(val)};
map.put(nums[i],i);
}
return new int[]{-1,-1};
}
}