1.题目描述
2.题目分析
给定数组与目标值,重点是找到数组中和为目标值的两个整数,并返回下标;这里有两个信息点,一是数组中数值本身,另一个是下标。若数组为有序数组则直接两端同时查找比较即可,但数组无序则无法直接查找,可以先排序再查找,这样与暴力查找的时间复杂度相同,不可取。所以我们再次把目光聚焦到两个信息点,要找个两个数值有函数关系,下标与之一一对应,那么我们就可以用哈希表将两个信息存储起来,同时无重复元素无多解,哈希性能好。
3.哈希表详解
(1)概念
哈希表又叫散列表,是基于数组的一种数据结构,存储键值对,它可以快速查找和快速插入,查找与插入的时间复杂度为O(1);它建立关键字(即键)与下标(即值)的关系映射,这个映射即为哈希函数。
哈希表在Java中为HashMap,使用方法如下:
var map=new HashMap<Object,Object>();//声明
Object a1,Object a2;
map.put(a1,a2);//插入
var a3=map.get(a1);//查找=a2
boolean is=map.containsKey(a1);//是否存在a1
哈希函数如下:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
哈希函数的作用就是建立键与值的关系,一般情况下它取模:
关键字%数组大小
数组大小一般为质数
这时就会出现关键字不同但是哈希值相同的情况,即哈希冲突;
比如12 mod 13=12,38 mod 13=12。解决哈希冲突的方法有两种,链表法和开放地址法。
(2)链表法
链表法即写结构体时加入next指针,冲突时将数据放入next中。
(2)开放地址法
1.线性探测法
遇到冲突寻找下一个位置,新位置=原位置+i(冲突次数);
2.平方探测法
遇到冲突寻找下一个位置,新位置=原位置+i^2(冲突次数);
3.双哈希
新增一个哈希函数hash2,当遇到冲突时新位置=原位置+i*hash2(key);
hash2(key)=R-(key mod R)
//R:小于数组大小的质数
(3)补充
1.优点:内存少于数组,查找速度优于链表;隐蔽了内部数据。
2.缺点:存在哈希冲突,且表越满,性能越差。
3.一般情况下,当表容量大于70%时,新建哈希表,且总容量为原表的2倍。
3.题解
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++)
{
if(map.containsKey(target-nums[i]))
{
return new int[]{map.get(target-nums[i]),i};
}
map.put(nums[i],i);
}
return null;
}
}