这个算法是我用Java写的,需要别的语言版本的,推荐一个博客网站,上面有各种语言版本。 别的语言版本在这里!
1.题目
原题目在这里! 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
示例 1: 输入:nums = [2,7,11,15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 。
示例 2: 输入:nums = [3,2,4], target = 6 因为 nums[1] + nums[2] = 2+4=6 所以返回[1,2]
示例 3: 输入:nums = [3,3], target = 6 因为nums[0] + nums[1] = 3+3 = 6 所以返回[0, 1] 。
2.暴力枚举
这种问题我们最容易想到的是暴力枚举,就是使用两层for循环来解决。
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result=new int[2]; //用数组result来存储满足条件的数据的下表。
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){ //这里为什么j=i+1;这样写,你思考一下就明白了。
if(nums[i]+nums[j]==target){
result[0]=i;
result[1]=j;
break; //如果满足if条件,就把下表依次存到result数组当中,然后break打破循环。
}
}
}
return result;
}
}
算法分析
时间复杂度的分析
- 外层循环(由i控制)从数组的第一个元素开始,一直到最后一个元素。
- 内层循环(由j控制)从i的下一个元素开始,也是一直到最后一个元素。
模拟执行过程:
- 当i为0时,内层循环将执行n-1次。注意,数组的长度是n。
- 当i为1时,内层循环将执行n-2次。
- …
- 当i为n-2时,内层循环将执行1次。
- 当i为n-1时,内层循环将不执行。注意:因为数组的下标是0开始的,所以n-1是最后一个元素。
如果我们将所有可能的 j 值的数量加起来,我们得到:
带入等差数列求和公式得到:
所以时间复杂度为:O(n^2)。
更简单估算的方法: 我们能很容易看出外层循环的时间复杂度为O(n),内层循环的平均时间复杂度为O(n/2),所以总的时间复杂度为O(n*n/2),即O(n^2)。
空间复杂度分析
空间复杂度为O(1),因为它只使用了常量级的额外空间来存储变量i,j。
3.使用哈希表
如果想查看详细的讲解,可以查看代码随想录,这里的博客写的真的非常好。 详细讲解在这里! 注意,在这个代码中的哈希表是以下面的形式存储数据的。
- nums[i] 是键(key)。
- i 是值(value)。
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result=new int[2]; ////用数组result来存储满足条件的数据的下表
//判断数组是否为 空 或者 长度等于0(其实我有点疑惑数组的长度怎么能等于0 哈哈)
if(nums==null || nums.length==0){
return result;
}
//如果不是空 或者 长度等于0,就开始使用哈希表
Map<Integer,Integer> map=new HashMap<>(); //Map是HashMap父亲,所以这里使用多态的思想
for(int i=0;i<nums.length;i++){
int temp=target-nums[i]; //通过计算target-nums[i]得到与之配对的补数temp
//比如:9-2=7,要判断这个7是不是在哈希表里面
if(map.containsKey(temp)){
result[0]=map.get(temp); //得到temp这个数据对应的下标。
result[1]=i;
break;
}
map.put(nums[i], i); // 如果没找到匹配对,就把访问过的元素和下标加入到map中
}
return result;
}
}
时间复杂度分析
由于只需要遍历一次数组,且哈希表的查找操作的时间复杂度为 O(1),因此总体时间复杂度为 O(n)。
空间复杂度分析
空间复杂度方面,额外使用了一个哈希表 map,其所需空间取决于输入数组的大小,因此空间复杂度为 O(n)。