题目:
示例&提示:
>所属知识点:哈希表(题解二)
题解1:暴力枚举:
可以通过两个循环遍历整个数组找出和为target的整数:
public class twoSum {
public int[] twoSum(int[]nums,int target) {
int len = nums.length;
for(int i = 0;i < len - 1;i++) {
for(int j = i + 1;j < len;j++) {
if(nums[i] + nums[j] == target) {
return new int[] {i,j}; //返回包含两个索引的新数组
}
}
}
//遍历完所有可能组合后仍无解,抛出异常,异常表示无解
throw new IllegalArgumentException("no two sum solution.");
//抛出不合法或无效参数的异常类。异常处理放双层for循环外面
}
}
可以看出时间复杂度为O(N^2),空间复杂度为O(1)。但是,我们能不能想出一个时间复杂度小于O(N^2)的算法呢?
那么接下来就来到我们的题解二:哈希表
题解二:哈希表:
对哈希表这个知识点不熟悉的可以参考这篇文章,通俗易懂:通俗易懂->哈希表详解-CSDN博客
简单来说,哈希表的作用就是:假设你有一本电话本,你想要查找张三的电话号码(12345678910),当你想要找到张三的电话号码时,不需要一页一页翻,直接查名字就能立刻找到号码。哈希表就是这种【快速查字典】的结构:
· Key(键) ——> 类似电话本中的[【名字】,如数字2
· Value(值) ——> 类似电话本中的[【号码】,如数字2的索引0
· 存入数据用hashtable.put(key,value);查找数据用hashtable.containsKey(key)判断是否存在
回归题目:
这里用了补数的思想,而非凑数的方法。
遍历数组查找是否存在【补数 target-nums[i]】 :
①如果补数不存在,则将当前数字及其索引存入哈希表中,以供后续元素查询;
②如果补数已经存在于哈希表中,说明找到了两个数的和为target,直接返回它俩的索引。
public class twoSum {
public int[] twoSum(int[]nums,int target) {
Map<Integer,Integer> hashTable = new HashMap<>(); //初始化哈希表,哈希表此时为空
for(int i = 0;i < nums.length;i++) {
if(hashTable.containsKey(target-nums[i])) { //检查补数是否存在
return new int[] {hashTable.get(target-nums[i]),i}; //补数存在则返回两个数的索引
}
hashTable.put(nums[i], i);//补数不存在,则存储当前数字及其索引至哈希表中,以供后续元素查询
}
throw new IllegalArgumentException("no two sum solution");
}
}
图解:
时间复杂度降到O(N),只需遍历一次数组,每次查询补数只需O(1)时间;空间复杂度升到O(N),其中N是数组中的元素数量。主要为哈希表的开销。