内容:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
中文意思:给出一个顺序整数数组,返回两个加起来等于指定的质数。
假设每次输入只有唯一解法,而不能用相同数。
例子:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
一开始就没有想用暴力解法,想先通过快速排序然后过滤一部分不可能整数。最后采用来寻找这两个值。其实一开始现没有看到提示,提示说到用hashTable。最后自己完成一份代码直接效率很低,后面发现直接连暴力解法都不如。
首先列出暴力解法的代码(时间复杂度 O(n^2),空间复杂度O(1) ),成绩为15ms,38MB。
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[j] == target - nums[i]) {
return new int[] { i, j };
}
}
}
throw new IllegalArgumentException("No two sum solution");
}
但是我发现一个奇怪现象,即使将判断语句转化一下
if (nums[j] + nums[i] == target )
最后执行结果为19ms,38MB。试过好几次,速度都这样。暂时没有弄明白原因,后续通过编译之后代码查看原因
目前该题目采用最优解法就是利用HashTable这个集合,将所有对象放入HashTable,利用HashTable快速定位是否存在对应数值方式来实现快速查找。
HashTable遇到哈希冲突的时候,总体性能会下降,后续可以深入哈希冲突相关内容
时间复杂度 O(n),空间复杂度O(1),以下为遍历两次和遍历一次。
遍历两次
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");
}
遍历一次
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");
}
课后学习点:
1、本题目为什么采用HashTable,利用其它集合性能差异,差异原因
2、哈希冲突
3、加法与减法在if判断中是否存在性能差异