两数之和
题目链接:
https://leetcode-cn.com/problems/two-sum/
题目描述
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
题目详解
这道题目给我们一个数组,数组里面全是整数,然后再给我们一个数字 target ,需要我们求出在这个数组中哪两个数字的和正好是 target 。注意,你不能重复利用这个数组中同样的元素,指的是每一个位置上的数字只能被使用一次,比如数组 [1,1,3],你可以使用第一个和第二个 1,但是你不能使用第一个 1 两次。
解题方案
思路 1:时间复杂度: O(N^2) 空间复杂度: O(1)
这种方法很简单,就是暴力解法,双重循环遍历就可以了 。外层循环从数组中取出下标为 i 的元素 num[i] ,内层循环取出 i 之后的元素 nums[j] 一一与下标为 i 的元素进行相加操作,判断结果是否为 target 。题目只要求找到一种,所以一旦找到直接返回。时间复杂度中的 N 代表的是 nums 列表的长度。
下面我们来看代码:
class Solution {
public int[] twoSum(int[] nums, int target) {
// 第一轮遍历
for (int i = 0; i < nums.length; i++) {
// 第二轮遍历不能重复计算了
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
// 注意 leetcode 中要求返回的是索引位置
return new int[]{
i, j};
}
}
}
return null;
}
}
思路 2:时间复杂度: O(N) 空间复杂度: O(N)
上面的思路 1 时间复杂度太高了,是典型的加快时间的方法,这样做是不可取的。其实我们可以牺牲空间来换取时间。
我们希望,在我们顺序遍历取得一个数 num[1] 的时候,就知道和它配对的数 target - num1 是否在我们的 nums 里面,并且不单单只存在一个。比如说 target 为 4, nums 为 [2,3],假设我们此时取得的 num1 为 2,那么和它配对的 2 确实在 nums 中,但是数字 2 在 nums 中只出现了一次,我们无法取得两次,所以也是不行的。
因此我们有了下面的步骤:
- 创建一个 HashMap , key 存放 nums[i] ,value 存放索引 i ;
- 判断 HashMap 中是否存在 target - cur ,则当前值 cur 和某个 HashMap 中的 key 值相加之和为 target ;
- 如果存在,则返回 target - cur 的 index 与当前值 cur 的 index;
- 如果不存在则将当前数字 cur 为 key,当前数字的 index 为 value 存入 HashMap 。
下面我们来看下代码:
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
// 将原本为两个目标值切换为一个目标值,只需要每次从 map 中寻找目标值即可
int num = target - nums[i];
if (map.containsKey(num)) {
return new int[]{
map.get(num), i};
}
// 每次遍历过的值都存储到 map 中,这样之后就能从 map 中寻找需要的目标值
map.put(nums[i], i);
}
return null;
}
}