[leetcode]两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 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");
}
官方这样的做法时间复杂度是o(n),但是for循环里带containKey怎么会是o(n)呢?
原来map.containKey()的复杂度可以看做o(1):
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
// 直接命中
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
// 未命中
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
1. 指针first指向那一行数组的引用(那一行数组是通过table下标范围n-1和key的hash值计算出来的),若命中,则通过下标访问数组,时间复杂度为O(1)
2. 如果没有直接命中(key进行hash时,产生相同的位运算值),存储方式变为红黑树,那么遍历树的时间复杂度为O(n)。
另外,因为hashMap以key存hash,value是根据key所得。所以containValue()的时间复杂度为O(n),和containKey()不同。

浙公网安备 33010602011771号