일반적인 연결 리스트는 리스트의 마지막에서 노드를 연결시켜 추가하거나 마지막 노드를 삭제한다. Deque는 head와 tail을 통해 연결 리스트의 앞, 뒤로 노드를 추가하고 삭제할 수 있는 자료구조이다.
최댓값 및 최솟값을 찾아내는 연산을 빠르게 하기 위해 고안된 완전이진트리
파이썬에서는 heapq 모듈을 이용하여 heap을 구성할 수 있다. heapq 모듈은 기본적으로 Min Heap을 구성하도록 한다.
- heapq.heappush(heap: list, val: any) : heap에 val을 push하여 heap을 구성한다
- heapq.heappop(heap: list) : heap에서 가장 작은 원소를 빼내어 return
- heapq.heapify(heap: list) : 이미 생성한 리스트를 heapify를 통해 heap으로 만들어줌
- heapq.heappush(heap: list, val: tuple) : heap의 요소로 tuple을 넣을 수 있다. 이 경우 구현에 따라 Max Heap이나 Priority Queue를 구현할 수 있게 된다.
원형 Deque를 구현하는 문제이다. 주어진 함수를 구현하여 원형 Deque가 동작하도록 하면 된다.
InsertFront 예시, InsertLast도 같은 방법으로
DeleteFront 예시, DeleteLast도 같은 방법으로
class Node:
def __init__(self, value, right_node=None, left_node=None):
self.value = value
self.left = right_node
self.right = left_node
class MyCircularDeque:
def __init__(self, k: int):
self.head, self.tail = Node(None), Node(None)
self.max_size = k
self.cur_size = 0
self.head.right = self.tail
self.tail.left = self.head
def insertFront(self, value: int) -> bool:
if not self.isFull():
new_node = Node(value)
head_next = self.head.right
self.head.right, head_next.left = new_node, new_node
new_node.left, new_node.right = self.head, head_next
self.cur_size += 1
return True
return False
def insertLast(self, value: int) -> bool:
if not self.isFull():
new_node = Node(value)
tail_before = self.tail.left
self.tail.left, tail_before.right = new_node, new_node
new_node.left, new_node.right = tail_before, self.tail
self.cur_size += 1
return True
return False
def deleteFront(self) -> bool:
if not self.isEmpty():
head_right = self.head.right.right
head_right.left, self.head.right = self.head, head_right
self.cur_size -= 1
return True
return False
def deleteLast(self) -> bool:
if not self.isEmpty():
tail_before = self.tail.left.left
tail_before.right, self.tail.left = self.tail, tail_before
self.cur_size -= 1
return True
return False
def getFront(self) -> int:
if self.isEmpty():
return -1
return self.head.right.value
def getRear(self) -> int:
if self.isEmpty():
return -1
return self.tail.left.value
def isEmpty(self) -> bool:
return self.cur_size == 0
def isFull(self) -> bool:
return self.cur_size == self.max_size
연결리스트로 이루어진 배열을 받고, 모든 노드들이 정렬되어 있는 연결 리스트를 반환하는 문제이다.
lists = [ 1 → 4 → 5, 1 → 3, 2 → 4 ] 이면 1 → 1 → 2 → 3 → 4 → 4 → 5 를 반환한다.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
data = []
for li in lists:
cur = li
while cur:
data.append(cur.val)
cur = cur.next
data.sort()
result_root = result = ListNode()
while data:
node = ListNode(data.pop(0))
result.next = node
result = result.next
return result_root.next
heapq 모듈을 이용한다.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
root = result = ListNode(None)
heap = []
for i in range(len(lists)):
if lists[i]:
heapq.heappush(heap, (lists[i].val, i, lists[i]))
while heap:
node = heapq.heappop(heap)
idx = node[1]
result.next = node[2]
result = result.next
if result.next:
heapq.heappush(heap, (result.next.val, idx, result.next))
return root.next
다음의 기능을 제공하는 해시맵을 디자인하라
example)
MyHashMap myHashMap = new MyHashMap();
myHashMap.put(1, 1); // The map is now [[1,1]]
myHashMap.put(2, 2); // The map is now [[1,1], [2,2]]
myHashMap.get(1); // return 1, The map is now [[1,1], [2,2]]
myHashMap.get(3); // return -1 (i.e., not found), The map is now [[1,1], [2,2]]
myHashMap.put(2, 1); // The map is now [[1,1], [2,1]] (i.e., update the existing value)
myHashMap.get(2); // return 1, The map is now [[1,1], [2,1]]
myHashMap.remove(2); // remove the mapping for 2, The map is now [[1,1]]
myHashMap.get(2); // return -1 (i.e., not found), The map is now [[1,1]]
key와 value를 가지는 ListNode를 이용한다.
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
self.table = collections.defaultdict(ListNode)
def put(self, key: int, value: int) -> None:
index = key % self.size
if self.table[index].value is None:
self.table[index] = ListNode(key, value)
return
p = self.table[index]
while p:
if p.key == key:
p.value = value
return
if p.next is None:
break
p = p.next
p.next = ListNode(key, value)
def get(self, key: int) -> int:
index = key % self.size
if self.table[index].value is None:
return -1
p = self.table[index]
while p:
if p.key == key:
return p.value
p = p.next
return -1
def remove(self, key: int) -> None:
index = key % self.size
if self.table[index].value is None:
return
p = self.table[index]
if p.key == key:
self.table[index] = ListNode() if p.next is None else p.next
return
prev = p
while p:
if p.key == key:
prev.next = p.next
return
prev, p = p, p.next
# Your MyHashMap object will be instantiated and called as such:
# obj = MyHashMap()
# obj.put(key,value)
# param_2 = obj.get(key)
# obj.remove(key)