Java HashSet和ArrayList的查找Contains()时间复杂度

今天在刷leetCode时,碰到了一个题是这样的。

给定一个整数数组,判断是否存在重复元素。

如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。

看到这个题的第一时间,就想到了利用集合ArrayList来存储,并且判断。

代码:

 

    class Solution {
        public boolean containsDuplicate(int[] nums) {
            List<Integer> list=new ArrayList<>();
            for (int i=0;i<nums.length;i++){
                if(list.contains(nums[i])){
                    return true;
                }else {
                    list.add(nums[i]);
                }
            }
            return false;
        }
    }

 

然而,当数据量足够大的时候,会提示超出时间限制

后来又用了指针遍历数组,时间复杂度勉强通过,也不尽人意

最后又用到了HashSet,时间复杂度已经很好了

    public static boolean containsDuplicate(int[] nums) {
        Set<Integer> set=new HashSet<>();
        for (int i=0;i<nums.length;i++){
            if(set.contains(nums[i])){
                return true;
            }else {
                set.add(nums[i]);
            }
        }
        return false;
    }

这个时候。引发了我对这两者的思考,

这道题不但在考你的基础算法实现,还涉及到算法效率优化问题。也就是必须要关注算法的时间复杂度。

既然如此,就趁这个机会加深一下ArrayList与HashSet元素查找的时间复杂度区别,实际上就是底层的实现区别。

ArrayList本质就是通过数组实现的,查找一个元素是否包含要用到遍历,时间复杂度是O(n) 

而HashSetHashSet的查找是通过HashMap的KeySet来实现的,判断是否包含某个元素的实现,时间复杂度是O(1)

ArrayList判断是否包含某个元素的源码实现:

 public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

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;
    }

HashSet判断是否包含某个元素的源码实现:

public boolean contains(Object o) {
        return map.containsKey(o);
    }

 public boolean containsKey(Object key) {
        return getNode(hash(key), key) != null;
    }

   final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) { //直接通过hash确定元素位置,不用从头遍历
            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);
            }
        }
        return null;
    }

 

posted @ 2019-07-08 11:06  杰哥!  阅读(9571)  评论(1编辑  收藏  举报
/*scroll to top 火箭按钮*/