0%

两数之和

坚持就是胜利,开始刷题之旅

题目

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

1
2
3
4
5
给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9

所以返回 [0, 1]

思路

读懂这道题后的第一反应就是暴力向后搜索。但是这样的复杂度是O(n^2),肯定没有这么简单。只能通过空间来换时间,那么有什么查询方式是O(1)呢?第一反应是散列查找,也就是哈希查找。在java中。有HashMap类可以实现这个需求,那么代码可以是这个样子

代码

解法一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//初始化一个int对应int的hashmap
HashMap<Integer, Integer> m = new HashMap<Integer, Integer>();
//初始化结果数组
int[] res = new int[2];
//将题目给定的数组放入hashmap中
for (int i = 0; i < nums.length; i++) {
m.put(nums[i], i);
}
//开始搜索
for (int i = 0; i < nums.length; i++) {
//搜索值等于和减去当前值
int t = target - nums[i];
//在hashmap中搜索并且保证存在而且不等于当前值
if (m.containsKey(t) && m.get(t) != i) {
//对结果进行赋值,搜索到所以退出搜索
res[0] = i;
res[1] = m.get(t);
break;
}
}
return res;
}
};

提交上述代码,会发现内存消耗很大,时间也只是9ms超过了80%的人。一定有更优的解法。百度后发现可以将两个操作合二为一。上述解法先是将数组放入hashmap中,然后再进行查找。可不可以边放边找呢?先全部放入就是拿到前面的数去找后面的数。边放边找就是拿着后面的数去找前面的数。仔细想想,确实是这个道理。那么试试??

解法二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public int[] twoSum(int[] nums, int target) {
//初始化一个int对应int的hashmap
HashMap<Integer, Integer> m = new HashMap<Integer, Integer>();
//初始化结果数组
int[] res = new int[2];
//开始查找
for (int i = 0; i < nums.length; i++) {
//如果hashmap中存在和减去当前数的数字
if(m.containsKey(target - nums[i])){
//赋值,表示查找到,用后数找前数,所以需要换一下位置
res[1]=i;
res[0]=m.get(target - nums[i]);
break;
}
//关键,每次循环都要放一个数到hashmap中,在查找中,拿着前数总是找不到后数的,因为还没有放进去,但是总会循环到后数,拿着后数的时候,前数已经放进去了,总是能找到的。所以这个方法很精妙,没有问题。
m.put(nums[i], i);
}
return res;
}
}

上述方法快了1ms,内存消耗也少了。