题目
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
解法
class Solution {
public int[] twoSum(int[] nums, int target) {
int result[] = new int[2];
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
result[0] = i;
result[1] = j;
return result;
}
}
}
return result;
}
}
分析
- 时间复杂度O(n^2)
- 常规思路,没亮点
- 执行效率较低
- 没再过多的定义变量(优点)
官方解法(一)
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[] { i, map.get(complement) };
}
}
throw new IllegalArgumentException("No two sum solution");
}
}
官方解法(二)
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
}
分析
这个解法很奇特,涉及到哈希表和hashmap,官方解法如果初始化好hashmap长度更好。
有大侠问,hashmap的put难道不耗时?containsKey难道不耗时?
个人理解:
- hashmap是数组+链表存储,java1.8版本,哈希碰撞达到一定阀值,链表会被转换成红黑树。
- containsKey 通常情况下时间复杂度是O(1),最糟糕的情况是O(n)。
- 为了对运行时间复杂度进行优化,我们需要一种更有效的方法来检查数组中是否存在目标元素。如果存在,我们需要找出它的索引。保持数组中的每个元素与其索引相互对应的最好方法是什么?哈希表。(官方原话,纯复制)
- 以空间换时间,查找时间从 O(n)降低到 O(1)
- 官方解法(二)解法更为巧妙