题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。
试例
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
返回 [0, 1]
解释:因为 nums[0] + nums[1] == 9
解法
方法一
利用数组实现,两层for循环,第一次循环取一个数,第二次循环取剩余的数一次与前一次循环所取的数进行判断,直到满足条件为止。
(此方法比较慢,用时间换取空间)
复杂度
时间复杂度:O()
空间复杂度:O(1)
代码实现
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] nu = new int[2];//定义一个数组用于存储下标值
for (int i = 0; i < nums.length-1; i++) {//第一层循环,拿第一个数
for (int j = i+1; j < nums.length; j++) {//第二层循环拿第二个数
if ((nums[i]+ nums[j] == target)){//判断两数相加是否等于target
nu[0] = i;//存储元素
nu[1] = j;
}
}
}
return nu;
}
}
方法二
(先存再判断)
利用map集合实现,map的key部分存储数组的元素,map的value存储数组下标,先赋值,后利用containsKey方法判断目标值减去循环时的那个数返回的key是否存在,如果存在则把i和返回的key存储到结果数组中。(用空间换取时间)
复杂度
时间复杂度:O(n)
空间复杂度:O(n)
代码实现
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();//定义一个map集合key部分存储数组的值,value部分存储数组的下标
for (int i = 0; i < nums.length; i++) {//循环给map赋值
map.put(nums[i],i);
}
for (int i = 0; i < nums.length; i++) {
//利用containsKey方法判断是否存在目标值减去数组循环取的值返回的key并且返回的key不能等于i
if (map.containsKey(target-nums[i])&&map.get(target-nums[i]) != i){
return new int[]{i,map.get(target-nums[i])};//返回结果数组
}
}
return new int[1];
}
}
优化代码
(边存边判断)
这个是我在leetcode中评论中发现别人写的代码,代码执行效率比较高。他的方法是先利用containsKey方法判断是否存在这样满足条件的数,若存在则返回输出结果,若不存在则对map进行赋值,不过此时map中的key部分就不是数组中的值了而是目标值减去数组中的值,原理上与第二种方法差不多,但是他是直接边存边判断,第二种方法是先存在判断,因此速度提升了许多。
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] indexs = new int[2];
// 建立k-v ,一一对应的哈希表
HashMap<Integer,Integer> hash = new HashMap<Integer,Integer>();
for(int i = 0; i < nums.length; i++){
if(hash.containsKey(nums[i])){
indexs[0] = i;
indexs[1] = hash.get(nums[i]);
return indexs;
}
// 将数据存入 key为补数 ,value为下标
hash.put(target-nums[i],i);
}
return indexs;
}
}