Java HashSet和ArrayList的查找Contains()時間復雜度


今天在刷leetCode時,碰到了一個題是這樣的。

給定一個整數數組,判斷是否存在重復元素。

如果任何值在數組中出現至少兩次,函數返回 true。如果數組中每個元素都不相同,則返回 false。

看到這個題的第一時間,就想到了利用集合ArrayList來存儲,並且判斷。

代碼:

class Solution {
    public boolean containsDuplicate(int[] nums) {
            Set<Integer> list=new HashSet<>();
        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;
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM