[Quetion]
- 문자열 삽입, 삭제, 랜덤 조회 함수 만들기
- 평균 O(1)의 시간복잡도
- 이미 문자열이 있을 때 삽입시 False
- 문자열이 없을 때 삭제시 False
O(1)의 시간복잡도로 접근하기 위해서는 Hashmap을 활용해야 겠다고 생각했다.
문자열이 없을 때 삭제시 False를 반환하는 것은 stack을 구현할 때의 stack underflow가 떠올랐다.
class RandomizedSet:
def __init__(self):
self.ran_set=[]
self.ran_hash={}
def insert(self, val: int) -> bool:
if val in self.ran_hash.keys():
return False
else:
self.ran_hash[val]=None
self.ran_set.append(val)
return True
def remove(self, val: int) -> bool:
try:
del self.ran_hash[val]
self.ran_set.remove(val)
return True
except KeyError:
return False
def getRandom(self) -> int:
return random.choice(self.ran_set)
Runtime: 349ms | Memory: 63.5MB
LeetCode 코드 중 Runtime 53%, Memory 95% 해당하는 결과
시간복잡도는 O(1), 공간복잡도는 O(N)이 나왔다.
dictionary.get('key')로 key값이 없으면 None으로 확인가능 했지만 key가 있음에도 None이 출력되는 상황을 발견해서 try except 구문으로 KeyError를 응용하여 구현했다.
리스트와 딕셔너리를 모두 사용하며 삽입, 삭제하기 때문에 조금 비효율적이라고 생각해서 set()의 특징을 활용하여 개선해보았다.
class RandomizedSet:
def __init__(self):
# ran_hash를 중복이 없는 집합으로 선언
self.ran_hash=set()
def insert(self, val: int) -> bool:
if val in self.ran_hash:
return False
self.ran_hash.add(val)
return True
def remove(self, val: int) -> bool:
if val in self.ran_hash:
self.ran_hash.remove(val)
return True
return False
def getRandom(self) -> int:
return random.choice(list(self.ran_hash))
Runtime: 349ms ---> 493ms
Memory: 63.5MB ---> 63.7MB
코드는 간결해졌지만 list, hashmap 두 가지를 모두 활용한 방법보다 오히려 성능적으로 떨어지게 되었다.
list(self.ran_hash)
로 집합을 list로 변환하는 과정에서 O(N)의 시간복잡도가 되었고, 평균적으로 시간복잡도가 증가하여 더 좋지 못한 성능이 나온 것 같다.
그래서 Hashmap만 활용하여 구현을 해보았지만 set()과 마찬가지로 getRandom()함수에서 O(N)의 시간복잡도가 걸렸다.
결과적으로 처음 작성한 코드가 성능적으로는 가장 우수했다는 것을 알았고, 대부분의 솔루션 코드도 같은 방법으로 접근한 것을 확인했다.