๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
์•Œ๊ณ ๋ฆฌ์ฆ˜/๋ฌธ์ œ

[์ž๋ฐ”] ๋ฆฌํŠธ์ฝ”๋“œ 706 - Design HashMap

by applemango2021 2021. 3. 7.

HashMap์€ Map์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์ด๊ธฐ ๋•Œ๋ฌธ์—, <key, value> ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. ํ•ญ์ƒ ์ฃผ์–ด์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉ๋งŒ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜์–ด ์žˆ๋Š”์ง€์— ๋Œ€ํ•ด์„œ๋Š” ๊ณ ๋ฏผํ•ด๋ณด์ง€ ์•Š์•˜๋Š”๋ฐ ๋•๋ถ„์— bucket์ด๋ผ๋Š” ๊ฐœ๋…๋„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. 

์ด๋ฒˆ ๋ฌธ์ œ๋Š” ๊ณต๋ถ€ํ•˜๋Š” ์ฐจ์›์—์„œ ํ‘ผ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋ฐ”๋กœ ํ’€์ด๋“ค์„ ์ข€ ์ฐพ์•„ ๋ณด์•˜๋‹ค. 

 

์ฒซ ๋ฒˆ์งธ Solution

์–ด์ฐจํ”ผ key์˜ ๋ฒ”์œ„๊ฐ€ 0๋ถ€ํ„ฐ 1,000,000, ์ฆ‰ ๋ฐฑ๋งŒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•ด์„œ ๊ตฌํ˜„ํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค. 

MyHashMap ํด๋ž˜์Šค ์ƒ์„ฑ ์‹œ์—, ํฌ๊ธฐ 1000001์ธ ๋ฐฐ์—ด์„ ์„ ์–ธํ•œ ๋‹ค์Œ์— index๋ฅผ ํ‚ค๊ฐ’์ฒ˜๋Ÿผ ์ƒ๊ฐํ•ด์„œ ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค. 

  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : O(1) (get, remove, put ๋ชจ๋‘์— ํ•ด๋‹น๋œ๋‹ค)
  • ๊ณต๊ฐ„ ๋ณต์žก๋„ : O(n)
class MyHashMap {
    
    int[] map;
    
    /** Initialize your data structure here. */
    public MyHashMap() {
        
        map = new int[1000001];
        Arrays.fill(map, -1);
    }
    
    /** value will always be non-negative. */
    public void put(int key, int value) {
        map[key+1] = value;
        
    }
    
    /** Returns the value to which the specified key is mapped, 
    or -1 if this map contains no mapping for the key */
    public int get(int key) {
        return map[key+1];
        
    }
    
    /** Removes the mapping of the specified value key if this map contains a mapping for the key */
    public void remove(int key) {
        map[key+1] = -1;
    }
}

/**
 * Your MyHashMap object will be instantiated and called as such:
 * MyHashMap obj = new MyHashMap();
 * obj.put(key,value);
 * int param_2 = obj.get(key);
 * obj.remove(key);
 */

 

 

๋‘ ๋ฒˆ์งธ Solution

์กฐ๊ธˆ ๋” ๋ณต์žกํ•˜๋‹ค. Bucket์˜ ๊ฐœ๋…์„ ์ด์šฉํ•˜๋Š”๋ฐ, Bucket์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” LinkedList๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. 

์ด ํ’€์ด๋ฒ•์€ ์•„๋ž˜ ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ์กฐํ–ˆ๋‹ค. ์ •๋ง ์ž˜ ์„ค๋ช…ํ•ด๋†“์•˜๋‹ค! 

developer-hongjoo.tistory.com/33?category=815694

 

[์•Œ๊ณ ๋ฆฌ์ฆ˜] Hash Table ๊ตฌํ˜„ํ•˜๊ธฐ

leetcode.com/problems/design-hashmap/ Design HashMap - LeetCode Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next int..

developer-hongjoo.tistory.com

์ฝ์œผ๋ฉด์„œ ์‹ค์ œ HashMap  ๊ตฌํ˜„ ๋กœ์ง๊ณผ ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๋„๋ก ์œ ์˜ํ•ด์•ผ ํ•  ๋ถ€๋ถ„์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. 

ํ˜„์žฌ ๋กœ์ง์—์„œ๋Š” key๊ฐ’์ด ์œ„์น˜ํ•  bucket์˜ index๋ฅผ ๊ฒฐ์ •์ง“๊ธฐ ์œ„ํ•ด  ์ž„์˜๋กœ key๋ฅผ BUCKET_CAPACITY๋กœ ๋‚˜๋ˆ„์—ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ํ•˜๋ฉด BUCKET_CAPACITY์— ๋”ฐ๋ผ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ ๋‹ฌ๋ผ์งˆ ๊ฒƒ ๊ฐ™์€๋ฐ, ์‹ค์ œ Hash Function์ด ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑ๋˜๋Š” ์ง€๋„ ๊ถ๊ธˆํ•˜๋‹ค. 

โ€ป ๋งŒ์•ฝ BUCKET_CAPACITY = 2๋ผ๋ฉด, bucket ๋ฐฐ์—ด ํ•˜๋‚˜์— ์ตœ๋Œ€ 2๊ฐœ์˜ node๋งŒ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์„ฑ๋Šฅ์ด ์ข‹์•„์งˆ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. 

index key
0 0~99
1 100~199
~ ~
9,999 999,900~999,999
10,000 1,000,000

 

๋‘ ๊ฐ€์ง€ ๋‚ด๊ฐ€ ์ˆ˜์ •ํ•œ ๋ถ€๋ถ„์ด ์žˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ๋กœ, remove()์—์„œ bucket[index]์— ๋‹ฌ๋ฆฐ ๋…ธ๋“œ๊ฐ€ ๋”ฑ 1๊ฐœ์˜€์„ ๋•Œ์—๋Š” bucket[index] ์ž์ฒด๋ฅผ null๋กœ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ์„œ(line #89) putํ•  ๋•Œ์— ์•„๋ฌด ๋ฌธ์ œ ์—†์ด new Bucket์œผ๋กœ ๊ฐ’์„ ์ง‘์–ด๋„ฃ์„ ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. 

๋‘ ๋ฒˆ์งธ๋กœ, bucket ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๋ฅผ 10001๋กœ ๋Š˜๋ ธ๋‹ค. ๋“ค์–ด์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฐ’์˜ ๋ฒ”์œ„๊ฐ€ [0,1000000]๋ฉด 1000000์ด key๋กœ ๋“ค์–ด์™”์„ ๋•Œ์—๋Š” index๊ฐ€ 10000์ด์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

 

ํ˜„์žฌ ๋กœ์ง์ƒ์—์„œ๋Š” ์‹œ๊ฐ„ ๋ณต์žก๋„์™€ ๊ณต๊ฐ„ ๋ณต์žก๋„๊ฐ€ trade-off ๊ด€๊ณ„์— ์žˆ๊ณ , BUCKET_CAPACITY์— ๋”ฐ๋ผ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ ํฌ๊ฒŒ ๋ฐ”๋€” ๊ฒƒ ๊ฐ™๋‹ค. 

  • ์‹œ๊ฐ„ ๋ณต์žก๋„ :  O(BUCKET_CAPACITY) 
  • ๊ณต๊ฐ„ ๋ณต์žก๋„ :  O(n/BUCKET_CAPACITY)  ← ์—ฌ๊ธฐ์—์„œ์˜ n์€ key๋กœ ๋“ค์–ด์˜ฌ ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€๊ฐ’
class MyHashMap {

    static final int BUCKET_CAPACITY = 100;
    static Bucket[] buckets;
    
    class Bucket{
        Node node;
        public Bucket(Node node){
            this.node = node;
        }
    }
    
    class Node{
        int key;
        int value;
        Node next;
        
        public Node(int key, int value, Node next){
            this.key = key;
            this.value = value;
            this.next = next;
        }
    }
    
    /** Initialize your data structure here. */
    public MyHashMap() {
       buckets = new Bucket[10001];     
    }
    
    /** value will always be non-negative. */
    public void put(int key, int value) {
        int index = key/BUCKET_CAPACITY;
        
        if(buckets[index] == null){
            buckets[index] = new Bucket(new Node(key,value,null));
        }else{
            Node node = buckets[index].node;
            
            
            while(node!=null){
                if(node.key==key){
                    node.value = value;
                    return;
                }
                
                if(node.next==null){
                    node.next = new Node(key,value,null);
                    return;
                }
                
                node = node.next;
            }
        }
    }
    
    /** Returns the value to which the specified key is mapped, 
    or -1 if this map contains no mapping for the key */
    public int get(int key) {
        int index = key/BUCKET_CAPACITY;
        
        if(buckets[index]==null){
            return -1;
        }else{
            Node node = buckets[index].node;
            while(node!=null){
                if(node.key==key) return node.value;
                node = node.next;
            }
            
            return -1;
        }
    }
    
    /** Removes the mapping of the specified value key 
    if this map contains a mapping for the key */
    public void remove(int key) {
        int index = key/BUCKET_CAPACITY;
        
        if(buckets[index]==null) return;
        else{
            Node node = buckets[index].node;
            Node prev = null;
            
            while(node!=null){
                if(node.key==key){
                    if(prev==null){ //๋”ฑ ์ฒซ๋ฒˆ์งธ ๋…ธ๋“œ๊ฐ€ removeํ•˜๋ ค๋Š” ๊ฐ’์ผ๋•Œ
                        //Bucket์— node๊ฐ€ ๋”ฑ 1๊ฐœ์˜€์„ ๋•Œ๋Š”, 
                        //Bucket ์ž์ฒด๋„ clear ์‹œ์ผœ์ค€๋‹ค. 
                        buckets[index].node = node.next;
                        if(node.next==null) buckets[index] = null; 
                        return;
                    }else{
                        prev.next = node.next;
                        return;
                    }
                    
                }else{
                    prev = node;
                    node = node.next;
                }
            }
        }
    }
}

/**
 * Your MyHashMap object will be instantiated and called as such:
 * MyHashMap obj = new MyHashMap();
 * obj.put(key,value);
 * int param_2 = obj.get(key);
 * obj.remove(key);
 */