[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()不同。

  

  

原文地址:https://www.cnblogs.com/lizhang4/p/10569835.html