정렬 알고리즘
====
병합 정렬
----
`안정적`
시간 복잡도: O(n log n)
공간 복잡도: O(n)
빠른 정렬
----
`불안정적`
평균 시간 복잡도: O(n log n), 이미 정렬되어 있거나 역순일 경우 최악의 경우 O(n^2)
공간 복잡도: O(log n)
메모리 교체 알고리즘
======
최근 사용되지 않은 것 제거 (LRU)
-------------------------------
LeetCode 146. LRU 캐시
만료 시간이 있는 LRU
---------
코드 보기
class Sorter {
public int[] sort(int[] arr) {
divide(arr, 0, arr.length - 1);
return arr;
}
private void divide(int[] arr, int start, int end) {
if (start >= end) return;
int mid = (start + end) / 2;
divide(arr, start, mid);
divide(arr, mid + 1, end);
combine(arr, start, mid, end);
}
private void combine(int[] arr, int leftStart, int leftEnd, int rightEnd) {
int[] temp = new int[rightEnd - leftStart + 1];
int i = leftStart, j = leftEnd + 1, k = 0;
while (i <= leftEnd && j <= rightEnd) {
if (arr[i] <= arr[j]) temp[k++] = arr[i++];
else temp[k++] = arr[j++];
}
while (i <= leftEnd) temp[k++] = arr[i++];
while (j <= rightEnd) temp[k++] = arr[j++];
System.arraycopy(temp, 0, arr, leftStart, temp.length);
}
}
코드 보기
class QuickSorter {
public int[] sort(int[] arr) {
quick(arr, 0, arr.length - 1);
return arr;
}
private void quick(int[] arr, int start, int end) {
if (start >= end) return;
int pivotIndex = partition(arr, start, end);
quick(arr, start, pivotIndex - 1);
quick(arr, pivotIndex + 1, end);
}
private int partition(int[] arr, int start, int end) {
int pivot = arr[start];
int i = start;
for (int j = start + 1; j <= end; j++) {
if (arr[j] <= pivot) {
i++;
swap(arr, i, j);
}
}
swap(arr, start, i);
return i;
}
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
코드 보기
class LRUCache {
private static class CacheNode {
int key, value;
CacheNode prev, next;
CacheNode(int k, int v) {
key = k;
value = v;
}
}
private final Map map = new HashMap<>();
private final CacheNode dummy = new CacheNode(0, 0);
private final int capacity;
public LRUCache(int capacity) {
this.capacity = capacity;
dummy.next = dummy;
dummy.prev = dummy;
}
public int get(int key) {
CacheNode node = fetchNode(key);
return node != null ? node.value : -1;
}
public void put(int key, int value) {
CacheNode node = fetchNode(key);
if (node != null) {
node.value = value;
return;
}
node = new CacheNode(key, value);
map.put(key, node);
appendToEnd(node);
if (map.size() > capacity) {
CacheNode first = dummy.next;
map.remove(first.key);
remove(first);
}
}
private CacheNode fetchNode(int key) {
if (!map.containsKey(key)) return null;
CacheNode node = map.get(key);
remove(node);
appendToEnd(node);
return node;
}
private void remove(CacheNode node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void appendToEnd(CacheNode node) {
CacheNode last = dummy.prev;
last.next = node;
node.prev = last;
dummy.prev = node;
node.next = dummy;
}
}
코드 보기
public class TimedLRUCache {
private static class TimedNode {
int key, value;
long expiry;
TimedNode prev, next;
TimedNode(int k, int v, long e) {
key = k;
value = v;
expiry = e;
}
}
private final int capacity;
private final long duration;
private final TimedNode sentinel = new TimedNode(0, 0, 0);
private final Map keyMap = new HashMap<>();
public TimedLRUCache(int cap, long dur) {
capacity = cap;
duration = dur;
sentinel.next = sentinel;
sentinel.prev = sentinel;
}
public int get(int key) {
TimedNode node = retrieveNode(key);
return node != null ? node.value : -1;
}
public void put(int key, int value) {
long currentTime = System.currentTimeMillis();
TimedNode node = retrieveNode(key);
if (node != null) {
node.value = value;
node.expiry = currentTime + duration;
return;
}
node = new TimedNode(key, value, currentTime + duration);
append(node);
keyMap.put(key, node);
if (keyMap.size() > capacity) {
TimedNode oldest = sentinel.prev;
keyMap.remove(oldest.key);
remove(oldest);
}
}
private TimedNode retrieveNode(int key) {
if (!keyMap.containsKey(key)) return null;
TimedNode node = keyMap.get(key);
if (System.currentTimeMillis() > node.expiry) {
remove(node);
keyMap.remove(key);
return null;
}
remove(node);
append(node);
return node;
}
private void remove(TimedNode node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void append(TimedNode node) {
node.prev = sentinel;
node.next = sentinel.next;
sentinel.next.prev = node;
sentinel.next = node;
}
}