Implement the RandomizedSet class:
Follow up: Could you implement the functions of the class with each function works in average O(1) time?
class RandomizedSet:
def __init__(self):
"""
Initialize your data structure here.
"""
self.randomizedset = set()
def insert(self, val: int) -> bool:
"""
Inserts a value to the set. Returns true if the set did not already contain the specified element.
"""
if val in self.randomizedset:
return False
else:
self.randomizedset.add(val)
return True
def remove(self, val: int) -> bool:
"""
Removes a value from the set. Returns true if the set contained the specified element.
"""
if val in self.randomizedset:
self.randomizedset.remove(val)
return True
else:
return False
def getRandom(self) -> int:
"""
Get a random element from the set.
"""
randomlist = random.sample(self.randomizedset, 1)
return randomlist[0]
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()
init: set 생성
insert: 중복 있으면 return False, 없으면 add 후 return True
remove: 삭제하고자 하는 값이 있으면 remove 후 return True, 없으면 return False
getRandom: random.sample 이용해서 1개의 랜덤값 정하고 return
(random.sample 은 리스트로 반환하기 때문에 첫번째 값인 randomlist[0] 을 return)
런타임 실화??
convert the data into a python list in order to return a random element 때문이라고 한다.
remove is not O(1) 이기도...
class RandomizedSet:
def __init__(self):
self.data_map = {} # dictionary, aka map, aka hashtable, aka hashmap
self.data = [] # list aka array
def insert(self, val: int) -> bool:
# the problem indicates we need to return False if the item
# is already in the RandomizedSet---checking if it's in the
# dictionary is on average O(1) where as
# checking the array is on average O(n)
if val in self.data_map:
return False
# add the element to the dictionary. Setting the value as the
# length of the list will accurately point to the index of the
# new element. (len(some_list) is equal to the index of the last item +1)
self.data_map[val] = len(self.data)
# add to the list
self.data.append(val)
return True
def remove(self, val: int) -> bool:
# again, if the item is not in the data_map, return False.
# we check the dictionary instead of the list due to lookup complexity
if not val in self.data_map:
return False
# essentially, we're going to move the last element in the list
# into the location of the element we want to remove.
# this is a significantly more efficient operation than the obvious
# solution of removing the item and shifting the values of every item
# in the dicitionary to match their new position in the list
last_elem_in_list = self.data[-1]
index_of_elem_to_remove = self.data_map[val]
self.data_map[last_elem_in_list] = index_of_elem_to_remove
self.data[index_of_elem_to_remove] = last_elem_in_list
# change the last element in the list to now be the value of the element
# we want to remove
self.data[-1] = val
# remove the last element in the list
self.data.pop()
# remove the element to be removed from the dictionary
self.data_map.pop(val)
return True
def getRandom(self) -> int:
# if running outside of leetcode, you need to `import random`.
# random.choice will randomly select an element from the list of data.
return random.choice(self.data)
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()
init: [딕셔너리] data_map & [리스트] data 두개를 만들어줌
insert: 삽입하려는 값이 data_map 에 있으면 return False, 없으면 data_map 과 data 에 값을 넣어줌
remove: 삭제하려는 값이 data_map 에 없으면 return False, 있으면 (remove 함수를 사용하지 않고)
data 의 마지막에 위치한 값과 data_map 에서의 val index 를 구해서
삭제할 값과 마지막에 insert 한 값의 위치를 바꿔주기
data_map[last_elem_in_list] = index_of_elem_to_remove
data[index_of_elem_to_remove] = last_elem_in_list
self.data[-1] = val
해준 후 pop 을 이용해 val 삭제
last element 와 index 변환 안해주면 data 의 인덱스들 꼬여서 wrong answer 된다
getRandom: random.choice 를 이용