给定一个整数数组 nums
和一个目标值 target
,请你在该数组中找出和为gai目标值的 两个 整数。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
======================================================
其实就这样一个最简单的算法题,给我的启示却很大
解题思路:
使用hashMap做备忘录,遍历数组中的每一个元素,从map中查找是否有target-nums[i],如果有就返回结果,如果没有,就
map.put(nums[i],i) , 我们通过值为key查找值所对应的index
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");
}
这个我试过,通过最快5ms
后来我脑子有点抽,想用list去实现也可以啊,结果运行时间40ms
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
arraylist底层是数组啊,这跟暴力的双层循环出答案又有什么两样呢 = =
于是我又想到了bitset
以及自己实现的二进制,通过二进制对应index上的1 or 0来判断该数字在数组中有没有
结果会超出内存限制,总会存在 nums = [-9999999,9999999] ,target = 0 这样的输入
自己写的没有相应的扩容以及处理方式,还要处理负数的情况,十分麻烦,且保存index也十分棘手
....
我一直忽略了hashmap为什么会快,因为hash算法使存取的时间复杂度为O(1)
想要这个题运行速度比hashMap还快,实现一个适合这个题的儿童版 "hashMap"
....
首先hash算法的实现..
我们不知道测试的数组里面值是什么,就当是随机数,那既然是随机数的话 取余数,加法,乘法,除法,位运算等等都可以,
就直接和111111....做与运算好了
如果hash碰撞了,map里是用链表储存,我们没有必要,就用数组保存
用时2ms
下面是代码
class Solution {
public int[] twoSum(int[] nums, int target) {
final int len = nums.length;
int n = len - 1;
n |= 8191;
final int hash = n;
final int[] root = new int[n+1];
final int[] linked = new int[len];
for (int i = 1; i < len; i++) {
int self = nums[i];
int aim = target - self;
if (aim == nums[0]) {
return new int[]{0, i};
}
int aimRootIndex = root[aim & hash];
while (aimRootIndex != 0) {
if (nums[aimRootIndex] == aim) {
return new int[]{aimRootIndex, i};
}
aimRootIndex = linked[aimRootIndex];
}
int thisIndex = self & hash;
linked[i] = root[thisIndex];
root[thisIndex] = i;
}
return null;
}
}