Programming/leetcode

706. Design HashMap

홍열 2021. 2. 22. 10:08
728x90

해시맵 디자인 하는 문제 (파이썬은 Dict가 해시맵으로 볼 수 있다.)

 

해시맵 이론들...

 

해시맵에서 충돌했을때 해결 방법은 개별체이닝과 오픈어드레싱 방법이 있다.

 

개별 체이닝 - LinkedList로 데이터를 이어나가는 방법(O(n)도 걸릴수 있다.)

오픈어드레싱 - 충돌이 났을때, 그 주변을 선형으로 탐색해 적절한 위치에다 넣는것, (모든 원소가 반드시 자신의 해쉬값과 일치한다는 보장이 없음)

 

파이썬은 오픈어드레싱을 사용하고 있다.

 

해시맵 로드팩터 - 해시 테이블에 저장된 데이터 개수 n을 버킷의 개수 k로 나눈것

파이썬의 로드팩터는 0.66이고, 자바는 0.75이다.

이 비율을 넘어가면 각 언어에서 해시 테이블 공간을 재할당 한한다.

 

import sys
from itertools import combinations
import collections
import heapq

input = sys.stdin.readline

class ListNode:
    def __init__(self, key=None, value=None):
        self.key =key
        self.value = value
        self.next =None

class MyHashMap:
    def __init__(self):
        self.size = 1000
        #collection.detauldict는 조회시에 존재하지않을 경우 에러를 발생시키지 않고, default 객체를 만들어준다.
        #default 객체가 ListNode
        self.table = collections.defaultdict(ListNode)
    def put(self, key:int, value:int)->None:
        # 해싱 함수
        index = key % self.size

        # value에 접근했는데, self.table[index]가 없을 경우에는 default객체가 만들어진다.
        # default 객체의 value가 None이라는 것은 결국 값이 없다는것과 같다.
        if self.table[index].value is None:
            #값이 없는것
            self.table[index] = ListNode(key, value)
            return
        # 값이 있다면, 개별체이닝을 통해서 끝값으로 가서 넣자
        head = self.table[index]

        while head:
            #같은 key일 경우 value update
            if head.key == key:
                head.value = value
                return
            if head.next is None:
                # 이 부분이 없으면 head가 None일때 빠져나가버리므로, 뒤에서 head.next에 뭘 넣을수가 없다.
                # 따라서 head.next를 검사해서 None이면 while문을 빠져나가도록 해야한다.
                break
            head = head.next
        head.next = ListNode(key, value)


    def get(self, key:int)->int:
        index = key % self.size

        #접근했고, default로 만들어져서 None이네..그럼 값이 없는것이야
        if self.table[index].value is None:
            return -1
        #돌면서 key를 찾아서 value를 보내자

        head = self.table[index]

        while head:
            if head.key == key:
                return head.value
            head = head.next
        return -1

    def remove(self, key:int)->None:
        index = key % self.size

        # 접근했고, default로 만들어져서 None이네..그럼 값이 없는것이야
        if self.table[index].value is None:
            return

        head = self.table[index]

        #첫번째 값일때 next가 None이면 ListNode를 넣고, 뒤에 값이 있으면 뒤에껄로 변경하자
        if head.key == key:
            self.table[index] = ListNode() if head.next is None else head.next
            return

        #첫번째 값이 아니면 prev와 head를 넣고 찾아야한다.

        prev = head
        while head:
            if head.key == key:
                prev.next = head.next
                return
            prev, head = head, head.next