Skip to content

zerohertzLib.algorithm

Algorithm

Algorithm과 관련된 다양한 함수들

Modules:

Name Description
bisect
collections
fft
graph
prime
sort

Classes:

Name Description
DisjointSet

Vanilla disjoint set

DisjointSetRank

Disjoint set (union by rank)

DisjointSetSize

Disjoint set (union by size)

Functions:

Name Description
bellman_ford

Graph에서 시작 node로부터 모든 다른 node까지의 최단 경로 거리 계산

bfs

BFS를 수행하기 위한 function

bisect_left

Binary Search (left)

bisect_right

Binary Search (right)

bubble_sort

Bubble Sort Algorithm: 연속된 값들을 비교하여 가장 큰 값을 배열의 끝으로 이동시키는 방식으로 정렬

counting_sort

Counting Sort Algorithm: 각 숫자의 개수를 세어 정렬

dfs

DFS를 수행하기 위한 function

dijkstra

Graph에서 시작 node로부터 모든 다른 node까지의 최단 경로 거리 계산

floyd_warshall

Graph에서 모든 node 쌍 간의 최단 경로 거리 계산

heap_sort

Heap Sort Algorithm: 배열 요소들을 heap으로 구성한 다음, 최대 heap 속성을 이용하여 정렬

insertion_sort

Insertion Sort Algorithm: 각 값들을 이미 정렬된 부분의 올바른 위치에 삽입하는 방식으로 정렬

merge_sort

Merge Sort Algorithm: 분할 정복 방법을 사용하여 배열을 절반으로 나누고, 각 부분을 정렬한 다음 합치는 방식으로 정렬

quick_sort

Quick Sort Algorithm: Pivot을 선택하여 이보다 작은 요소는 왼쪽, 큰 요소는 오른쪽에 위치시키는 방식으로 분할 정복을 사용하여 정렬

radix_sort

Radix Sort Algorithm: 각 자릿수에 대해 개별적으로 정렬

selection_sort

Selection Sort Algorithm: 배열에서 가장 작은 값을 찾아 해당 값을 배열의 앞부분으로 이동시키는 방식으로 정렬

soe

Sieve of Eratosthenes

__all__ module-attribute

__all__ = ['bfs', 'dfs', 'soe', 'fft', 'bisect_right', 'bisect_left', 'bubble_sort', 'selection_sort', 'insertion_sort', 'merge_sort', 'quick_sort', 'heap_sort', 'counting_sort', 'radix_sort', 'dijkstra', 'floyd_warshall', 'bellman_ford', 'DisjointSet', 'DisjointSetRank', 'DisjointSetSize']

DisjointSet

DisjointSet(size: int, compression: bool = False)

Vanilla disjoint set

Note

Time Complexity:

  • Without path compression:
    • Worst: \(O(V)\)
    • Average: \(O(V)\)
  • With path compression:

    • Worst: \(O(\log{V})\)
    • Average: \(O(\alpha(V))\)
  • \(V\): Node의 수

  • \(\alpha(V)\): Ackermann function 의 역함수 (\(O(\alpha(V))\simeq O(1)\))

Parameters:

Name Type Description Default
size int

Node의 수

required
compression bool

Path compression 여부

False

Attributes:

Name Type Description
parent

Node에 따른 부모 node의 index

Examples:

>>> disjointset = zz.algorithm.DisjointSet(5)
>>> disjointset.union(0, 1)
>>> disjointset.union(2, 3)
>>> disjointset.union(1, 2)
>>> disjointset.parent
[0, 0, 0, 2, 4]
>>> disjointset = zz.algorithm.DisjointSet(5, True)
>>> disjointset.union(0, 1)
>>> disjointset.union(2, 3)
>>> disjointset.union(1, 2)
>>> disjointset.parent
[0, 0, 0, 2, 4]

Methods:

Name Description
find

목표 node에 대한 root node 탐색

union

두 node 연결

Source code in zerohertzLib/algorithm/collections.py
def __init__(self, size: int, compression: bool = False) -> None:
    self.parent = list(range(size))
    self.compression = compression

compression instance-attribute

compression = compression

parent instance-attribute

parent = list(range(size))

find

find(node: int) -> int

목표 node에 대한 root node 탐색

Parameters:

Name Type Description Default
node int

목표 node의 index

required

Returns:

Type Description
int

목표 node에 대한 root node의 index

Source code in zerohertzLib/algorithm/collections.py
def find(self, node: int) -> int:
    """목표 node에 대한 root node 탐색

    Args:
        node: 목표 node의 index

    Returns:
        목표 node에 대한 root node의 index
    """
    if not self.compression:
        while node != self.parent[node]:
            node = self.parent[node]
        return node
    if node != self.parent[node]:
        self.parent[node] = self.find(self.parent[node])
    return self.parent[node]

union

union(node1: int, node2: int) -> None

두 node 연결

Parameters:

Name Type Description Default
node1 int

목표 node의 index

required
node2 int

목표 node의 index

required

Returns:

Type Description
None

self.parent 에 root node의 index update

Source code in zerohertzLib/algorithm/collections.py
def union(self, node1: int, node2: int) -> None:
    """두 node 연결

    Args:
        node1: 목표 node의 index
        node2: 목표 node의 index

    Returns:
        `self.parent` 에 root node의 index update
    """
    root1, root2 = self.find(node1), self.find(node2)
    if root1 != root2:
        self.parent[root2] = root1

DisjointSetRank

DisjointSetRank(size: int)

Bases: DisjointSet

Disjoint set (union by rank)

Note

Time Complexity:

  • Worst: \(O(\log{V})\)
  • Average: \(O(\alpha(V))\)

  • \(V\): Node의 수

  • \(\alpha(V)\): Ackermann function 의 역함수 (\(O(\alpha(V))\simeq O(1)\))

Parameters:

Name Type Description Default
size int

Node의 수

required

Attributes:

Name Type Description
parent

Node에 따른 부모 node의 index

rank

Node에 따른 rank

Examples:

>>> disjointset = zz.algorithm.DisjointSetRank(5)
>>> disjointset.union(0, 1)
>>> disjointset.union(2, 3)
>>> disjointset.union(1, 2)
>>> disjointset.parent
[0, 0, 0, 2, 4]
>>> disjointset.rank
[2, 0, 1, 0, 0]

Methods:

Name Description
union

두 node 연결

Source code in zerohertzLib/algorithm/collections.py
def __init__(self, size: int) -> None:
    super().__init__(size, True)
    self.rank = [0 for _ in range(size)]

rank instance-attribute

rank = [0 for _ in (range(size))]

union

union(node1: int, node2: int) -> None

두 node 연결

Parameters:

Name Type Description Default
node1 int

목표 node의 index

required
node2 int

목표 node의 index

required

Returns:

Type Description
None

self.parent 에 root node의 index update

Source code in zerohertzLib/algorithm/collections.py
def union(self, node1: int, node2: int) -> None:
    """두 node 연결

    Args:
        node1: 목표 node의 index
        node2: 목표 node의 index

    Returns:
        `self.parent` 에 root node의 index update
    """
    root1, root2 = self.find(node1), self.find(node2)
    if root1 != root2:
        if self.rank[root1] > self.rank[root2]:
            self.parent[root2] = root1
        elif self.rank[root1] < self.rank[root2]:
            self.parent[root1] = root2
        else:
            self.parent[root2] = root1
            self.rank[root1] += 1

DisjointSetSize

DisjointSetSize(size: int)

Bases: DisjointSet

Disjoint set (union by size)

Note

Time Complexity:

  • Worst: \(O(\log{V})\)
  • Average: \(O(\alpha(V))\)

  • \(V\): Node의 수

  • \(\alpha(V)\): Ackermann function 의 역함수 (\(O(\alpha(V))\simeq O(1)\))

Parameters:

Name Type Description Default
size int

Node의 수

required

Attributes:

Name Type Description
parent

Node에 따른 부모 node의 index

size

Node에 따른 size

Examples:

>>> disjointset = zz.algorithm.DisjointSetSize(5)
>>> disjointset.union(0, 1)
>>> disjointset.union(2, 3)
>>> disjointset.union(1, 2)
>>> disjointset.parent
[0, 0, 0, 2, 4]
>>> disjointset.size
[4, 1, 2, 1, 1]
>>> [disjointset.size[disjointset.find(i)] for i in range(5)]
[4, 4, 4, 4, 1]

Methods:

Name Description
union

두 node 연결

Source code in zerohertzLib/algorithm/collections.py
def __init__(self, size: int) -> None:
    super().__init__(size, True)
    self.size = [1 for _ in range(size)]

size instance-attribute

size = [1 for _ in (range(size))]

union

union(node1: int, node2: int) -> None

두 node 연결

Parameters:

Name Type Description Default
node1 int

목표 node의 index

required
node2 int

목표 node의 index

required

Returns:

Type Description
None

self.parent 에 root node의 index update

Source code in zerohertzLib/algorithm/collections.py
def union(self, node1: int, node2: int) -> None:
    """두 node 연결

    Args:
        node1: 목표 node의 index
        node2: 목표 node의 index

    Returns:
        `self.parent` 에 root node의 index update
    """
    root1, root2 = self.find(node1), self.find(node2)
    if self.size[root1] < self.size[root2]:
        self.parent[root1] = root2
        self.size[root2] += self.size[root1]
    else:
        self.parent[root2] = root1
        self.size[root1] += self.size[root2]

bellman_ford

bellman_ford(graph: list[list[tuple[int, int]]], start: int) -> list[int] | None

Graph에서 시작 node로부터 모든 다른 node까지의 최단 경로 거리 계산

Note

Time Complexity: \(O(VE)\)

  • \(V\): Node의 수
  • \(E\): 간선의 수

Parameters:

Name Type Description Default
graph list[list[tuple[int, int]]]

Index (간선의 시작 node)에 따른 간선의 도착 node와 가중치 정보

required
start int

최단 경로 거리가 계신될 시작 node

required

Returns:

Type Description
list[int] | None

start 에서 graph 내 모든 다른 node 까지의 최단 경로 거리 (음의 cycle을 가질 시 None return)

Examples:

>>> graph = [[(1, 4), (2, 2), (3, 7)], [(0, 1), (2, 5)], [(0, 2), (3, 4)], [(1, 3)]]
>>> zz.algorithm.bellman_ford(graph, 0)
[0, 4, 2, 6]
>>> zz.algorithm.bellman_ford(graph, 1)
[1, 0, 3, 7]
>>> zz.algorithm.bellman_ford(graph, 2)
[2, 6, 0, 4]
>>> zz.algorithm.bellman_ford(graph, 3)
[4, 3, 6, 0]
>>> zz.algorithm.bellman_ford([[(1, -1)], [(0, -1)]], 0) is None
True
Source code in zerohertzLib/algorithm/graph.py
def bellman_ford(graph: list[list[tuple[int, int]]], start: int) -> list[int] | None:
    """Graph에서 시작 node로부터 모든 다른 node까지의 최단 경로 거리 계산

    Note:
        Time Complexity: $O(VE)$

        - $V$: Node의 수
        - $E$: 간선의 수

    Args:
        graph: Index (간선의 시작 node)에 따른 간선의 도착 node와 가중치 정보
        start: 최단 경로 거리가 계신될 시작 node

    Returns:
        `start` 에서 graph 내 모든 다른 node 까지의 최단 경로 거리 (음의 cycle을 가질 시 None return)

    Examples:
        >>> graph = [[(1, 4), (2, 2), (3, 7)], [(0, 1), (2, 5)], [(0, 2), (3, 4)], [(1, 3)]]
        >>> zz.algorithm.bellman_ford(graph, 0)
        [0, 4, 2, 6]
        >>> zz.algorithm.bellman_ford(graph, 1)
        [1, 0, 3, 7]
        >>> zz.algorithm.bellman_ford(graph, 2)
        [2, 6, 0, 4]
        >>> zz.algorithm.bellman_ford(graph, 3)
        [4, 3, 6, 0]
        >>> zz.algorithm.bellman_ford([[(1, -1)], [(0, -1)]], 0) is None
        True
    """
    n = len(graph)
    distance = [sys.maxsize for _ in range(n)]
    distance[start] = 0
    for cnt in range(n):
        for node in range(n):
            for node_, dist_ in graph[node]:
                if (
                    distance[node] != sys.maxsize
                    and distance[node_] > distance[node] + dist_
                ):
                    distance[node_] = distance[node] + dist_
                    if cnt == n - 1:
                        return None
    return distance

bfs

bfs(maps: list[list[int]], start: int) -> list[int]

BFS를 수행하기 위한 function

Parameters:

Name Type Description Default
maps list[list[int]]

입력 graph

required
start int

Graph의 시작 지점

required

Returns:

Type Description
list[int]

방문 순서

Examples:

>>> zz.algorithm.bfs([[], [2, 3, 4], [1, 4], [1, 4], [1, 2, 3]], 1)
[1, 2, 3, 4]
Source code in zerohertzLib/algorithm/graph.py
def bfs(maps: list[list[int]], start: int) -> list[int]:
    """BFS를 수행하기 위한 function

    Args:
        maps: 입력 graph
        start: Graph의 시작 지점

    Returns:
        방문 순서

    Examples:
        >>> zz.algorithm.bfs([[], [2, 3, 4], [1, 4], [1, 4], [1, 2, 3]], 1)
        [1, 2, 3, 4]
    """
    visit = [False for _ in range(len(maps))]
    results = []
    queue = deque()
    queue.append(start)
    visit[start] = True
    while queue:
        tmp = queue.popleft()
        results.append(tmp)
        for i in maps[tmp]:
            if not visit[i]:
                visit[i] = True
                queue.append(i)
    return results

bisect_left

bisect_left(sorted_list: list[int | float], value: int | float) -> int

Binary Search (left)

Parameters:

Name Type Description Default
sorted_list list[int | float]

정렬된 list

required
value int | float

찾고자하는 값

required

Returns:

Type Description
int

value 값이 sorted_list 에 삽입될 때 index

Examples:

>>> zz.algorithm.bisect_left([1, 3, 5], 2.7)
1
>>> zz.algorithm.bisect_left([1, 3, 5], 3)
1
>>> zz.algorithm.bisect_left([1, 3, 5], 3.3)
2
Source code in zerohertzLib/algorithm/bisect.py
def bisect_left(sorted_list: list[int | float], value: int | float) -> int:
    """Binary Search (left)

    Args:
        sorted_list: 정렬된 list
        value: 찾고자하는 값

    Returns:
        `value` 값이 `sorted_list` 에 삽입될 때 index

    Examples:
        >>> zz.algorithm.bisect_left([1, 3, 5], 2.7)
        1
        >>> zz.algorithm.bisect_left([1, 3, 5], 3)
        1
        >>> zz.algorithm.bisect_left([1, 3, 5], 3.3)
        2
    """
    low, high = 0, len(sorted_list)
    while low < high:
        mid = (low + high) // 2
        if sorted_list[mid] < value:
            low = mid + 1
        else:
            high = mid
    return low

bisect_right

bisect_right(sorted_list: list[int | float], value: int | float) -> int

Binary Search (right)

Parameters:

Name Type Description Default
sorted_list list[int | float]

정렬된 list

required
value int | float

찾고자하는 값

required

Returns:

Type Description
int

value 값이 sorted_list 에 삽입될 때 index

Examples:

>>> zz.algorithm.bisect_right([1, 3, 5], 2.7)
1
>>> zz.algorithm.bisect_right([1, 3, 5], 3)
2
>>> zz.algorithm.bisect_right([1, 3, 5], 3.3)
2
Source code in zerohertzLib/algorithm/bisect.py
def bisect_right(sorted_list: list[int | float], value: int | float) -> int:
    """Binary Search (right)

    Args:
        sorted_list: 정렬된 list
        value: 찾고자하는 값

    Returns:
        `value` 값이 `sorted_list` 에 삽입될 때 index

    Examples:
        >>> zz.algorithm.bisect_right([1, 3, 5], 2.7)
        1
        >>> zz.algorithm.bisect_right([1, 3, 5], 3)
        2
        >>> zz.algorithm.bisect_right([1, 3, 5], 3.3)
        2
    """
    low, high = 0, len(sorted_list)
    while low < high:
        mid = (low + high) // 2
        if value < sorted_list[mid]:
            high = mid
        else:
            low = mid + 1
    return low

bubble_sort

bubble_sort(arr: list[int]) -> list[int]

Bubble Sort Algorithm: 연속된 값들을 비교하여 가장 큰 값을 배열의 끝으로 이동시키는 방식으로 정렬

Parameters:

Name Type Description Default
arr list[int]

정렬할 정수 list

required

Returns:

Type Description
list[int]

오름차순으로 정렬된 list

Examples:

>>> zz.algorithm.bubble_sort([64, 34, 25, 12, 22, 11, 90])
[11, 12, 22, 25, 34, 64, 90]
Source code in zerohertzLib/algorithm/sort.py
def bubble_sort(arr: list[int]) -> list[int]:
    """Bubble Sort Algorithm: 연속된 값들을 비교하여 가장 큰 값을 배열의 끝으로 이동시키는 방식으로 정렬

    Args:
        arr: 정렬할 정수 list

    Returns:
        오름차순으로 정렬된 list

    Examples:
        >>> zz.algorithm.bubble_sort([64, 34, 25, 12, 22, 11, 90])
        [11, 12, 22, 25, 34, 64, 90]
    """
    arr_len = len(arr)
    for i in range(arr_len):
        for j in range(0, arr_len - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

counting_sort

counting_sort(arr: list[int]) -> list[int]

Counting Sort Algorithm: 각 숫자의 개수를 세어 정렬

Parameters:

Name Type Description Default
arr list[int]

정렬할 정수 list

required

Returns:

Type Description
list[int]

오름차순으로 정렬된 list

Examples:

>>> zz.algorithm.counting_sort([64, 34, 25, 12, 22, 11, 90])
[11, 12, 22, 25, 34, 64, 90]
Source code in zerohertzLib/algorithm/sort.py
def counting_sort(arr: list[int]) -> list[int]:
    """Counting Sort Algorithm: 각 숫자의 개수를 세어 정렬

    Args:
        arr: 정렬할 정수 list

    Returns:
        오름차순으로 정렬된 list

    Examples:
        >>> zz.algorithm.counting_sort([64, 34, 25, 12, 22, 11, 90])
        [11, 12, 22, 25, 34, 64, 90]
    """
    max_val = max(arr) + 1
    count = [0] * max_val
    for arr_ in arr:
        count[arr_] += 1
    idx = 0
    for value in range(max_val):
        for _ in range(count[value]):
            arr[idx] = value
            idx += 1
    return arr

dfs

dfs(maps: list[list[int]], start: int) -> list[int]

DFS를 수행하기 위한 function

Parameters:

Name Type Description Default
maps list[list[int]]

입력 graph

required
start int

Graph의 시작 지점

required

Returns:

Type Description
list[int]

방문 순서

Examples:

>>> zz.algorithm.dfs([[], [2, 3, 4], [1, 4], [1, 4], [1, 2, 3]], 1)
[1, 2, 4, 3]
Source code in zerohertzLib/algorithm/graph.py
def dfs(maps: list[list[int]], start: int) -> list[int]:
    """DFS를 수행하기 위한 function

    Args:
        maps: 입력 graph
        start: Graph의 시작 지점

    Returns:
        방문 순서

    Examples:
        >>> zz.algorithm.dfs([[], [2, 3, 4], [1, 4], [1, 4], [1, 2, 3]], 1)
        [1, 2, 4, 3]
    """
    visit = [False for _ in range(len(maps))]
    results = []

    def _dfs(start):
        visit[start] = True
        results.append(start)
        for i in maps[start]:
            if not visit[i]:
                _dfs(i)

    _dfs(start)
    return results

dijkstra

dijkstra(graph: list[list[tuple[int, int]]], start: int) -> list[int]

Graph에서 시작 node로부터 모든 다른 node까지의 최단 경로 거리 계산

Note

Time Complexity: \(O((V+E)\log{V})\)

  • \(V\): Node의 수
  • \(E\): 간선의 수

Parameters:

Name Type Description Default
graph list[list[tuple[int, int]]]

Index (간선의 시작 node)에 따른 간선의 도착 node와 가중치 정보

required
start int

최단 경로 거리가 계신될 시작 node

required

Returns:

Type Description
list[int]

start 에서 graph 내 모든 다른 node 까지의 최단 경로 거리 (음의 가중치에서는 정확하지 않음)

Examples:

>>> graph = [[(1, 4), (2, 2), (3, 7)], [(0, 1), (2, 5)], [(0, 2), (3, 4)], [(1, 3)]]
>>> zz.algorithm.dijkstra(graph, 0)
[0, 4, 2, 6]
>>> zz.algorithm.dijkstra(graph, 1)
[1, 0, 3, 7]
>>> zz.algorithm.dijkstra(graph, 2)
[2, 6, 0, 4]
>>> zz.algorithm.dijkstra(graph, 3)
[4, 3, 6, 0]
Source code in zerohertzLib/algorithm/graph.py
def dijkstra(graph: list[list[tuple[int, int]]], start: int) -> list[int]:
    r"""Graph에서 시작 node로부터 모든 다른 node까지의 최단 경로 거리 계산

    Note:
        Time Complexity: $O((V+E)\log{V})$

        - $V$: Node의 수
        - $E$: 간선의 수

    Args:
        graph: Index (간선의 시작 node)에 따른 간선의 도착 node와 가중치 정보
        start: 최단 경로 거리가 계신될 시작 node

    Returns:
        `start` 에서 graph 내 모든 다른 node 까지의 최단 경로 거리 (음의 가중치에서는 정확하지 않음)

    Examples:
        >>> graph = [[(1, 4), (2, 2), (3, 7)], [(0, 1), (2, 5)], [(0, 2), (3, 4)], [(1, 3)]]
        >>> zz.algorithm.dijkstra(graph, 0)
        [0, 4, 2, 6]
        >>> zz.algorithm.dijkstra(graph, 1)
        [1, 0, 3, 7]
        >>> zz.algorithm.dijkstra(graph, 2)
        [2, 6, 0, 4]
        >>> zz.algorithm.dijkstra(graph, 3)
        [4, 3, 6, 0]
    """
    distance = [sys.maxsize for _ in range(len(graph))]
    distance[start] = 0
    queue = [(0, start)]
    while queue:
        dist, node = heapq.heappop(queue)
        if distance[node] < dist:
            continue
        for node_, dist_ in graph[node]:
            if distance[node_] > dist + dist_:
                distance[node_] = dist + dist_
                heapq.heappush(queue, (dist + dist_, node_))
    return distance

floyd_warshall

floyd_warshall(graph: list[list[tuple[int, int]]]) -> list[list[int]] | None

Graph에서 모든 node 쌍 간의 최단 경로 거리 계산

Note

Time Complexity: \(O(V^3)\)

  • \(V\): Node의 수

Parameters:

Name Type Description Default
graph list[list[tuple[int, int]]]

Index (간선의 시작 node)에 따른 간선의 도착 node와 가중치 정보

required

Returns:

Type Description
list[list[int]] | None

모든 node 쌍에 대한 최단 경로 거리 (음의 cycle을 가질 시 None return)

Examples:

>>> graph = [[(1, 4), (2, 2), (3, 7)], [(0, 1), (2, 5)], [(0, 2), (3, 4)], [(1, 3)]]
>>> zz.algorithm.floyd_warshall(graph)
[[0, 4, 2, 6], [1, 0, 3, 7], [2, 6, 0, 4], [4, 3, 6, 0]]
Source code in zerohertzLib/algorithm/graph.py
def floyd_warshall(graph: list[list[tuple[int, int]]]) -> list[list[int]] | None:
    """Graph에서 모든 node 쌍 간의 최단 경로 거리 계산

    Note:
        Time Complexity: $O(V^3)$

        - $V$: Node의 수

    Args:
        graph: Index (간선의 시작 node)에 따른 간선의 도착 node와 가중치 정보

    Returns:
        모든 node 쌍에 대한 최단 경로 거리 (음의 cycle을 가질 시 None return)

    Examples:
        >>> graph = [[(1, 4), (2, 2), (3, 7)], [(0, 1), (2, 5)], [(0, 2), (3, 4)], [(1, 3)]]
        >>> zz.algorithm.floyd_warshall(graph)
        [[0, 4, 2, 6], [1, 0, 3, 7], [2, 6, 0, 4], [4, 3, 6, 0]]
    """
    n = len(graph)
    distance = [[sys.maxsize for _ in range(n)] for _ in range(n)]
    for i in range(n):
        distance[i][i] = 0
        for j, dist in graph[i]:
            distance[i][j] = dist
    for k in range(n):
        for i in range(n):
            for j in range(n):
                if (
                    distance[i][j] > distance[i][k] + distance[k][j]
                    and distance[i][k] != sys.maxsize
                    and distance[k][j] != sys.maxsize
                ):
                    distance[i][j] = distance[i][k] + distance[k][j]
    for i in range(n):
        if distance[i][i] < 0:
            return None
    return distance

heap_sort

heap_sort(arr: list[int]) -> list[int]

Heap Sort Algorithm: 배열 요소들을 heap으로 구성한 다음, 최대 heap 속성을 이용하여 정렬

Parameters:

Name Type Description Default
arr list[int]

정렬할 정수 list

required

Returns:

Type Description
list[int]

오름차순으로 정렬된 list

Examples:

>>> zz.algorithm.heap_sort([64, 34, 25, 12, 22, 11, 90])
[11, 12, 22, 25, 34, 64, 90]
Source code in zerohertzLib/algorithm/sort.py
def heap_sort(arr: list[int]) -> list[int]:
    """Heap Sort Algorithm: 배열 요소들을 heap으로 구성한 다음, 최대 heap 속성을 이용하여 정렬

    Args:
        arr: 정렬할 정수 list

    Returns:
        오름차순으로 정렬된 list

    Examples:
        >>> zz.algorithm.heap_sort([64, 34, 25, 12, 22, 11, 90])
        [11, 12, 22, 25, 34, 64, 90]
    """
    n = len(arr)
    for i in range(n // 2 - 1, -1, -1):
        _heapify(arr, n, i)
    for i in range(n - 1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i]
        _heapify(arr, i, 0)
    return arr

insertion_sort

insertion_sort(arr: list[int]) -> list[int]

Insertion Sort Algorithm: 각 값들을 이미 정렬된 부분의 올바른 위치에 삽입하는 방식으로 정렬

Parameters:

Name Type Description Default
arr list[int]

정렬할 정수 list

required

Returns:

Type Description
list[int]

오름차순으로 정렬된 list

Examples:

>>> zz.algorithm.insertion_sort([64, 34, 25, 12, 22, 11, 90])
[11, 12, 22, 25, 34, 64, 90]
Source code in zerohertzLib/algorithm/sort.py
def insertion_sort(arr: list[int]) -> list[int]:
    """Insertion Sort Algorithm: 각 값들을 이미 정렬된 부분의 올바른 위치에 삽입하는 방식으로 정렬

    Args:
        arr: 정렬할 정수 list

    Returns:
        오름차순으로 정렬된 list

    Examples:
        >>> zz.algorithm.insertion_sort([64, 34, 25, 12, 22, 11, 90])
        [11, 12, 22, 25, 34, 64, 90]
    """
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        while j >= 0 and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key
    return arr

merge_sort

merge_sort(arr: list[int]) -> list[int]

Merge Sort Algorithm: 분할 정복 방법을 사용하여 배열을 절반으로 나누고, 각 부분을 정렬한 다음 합치는 방식으로 정렬

Parameters:

Name Type Description Default
arr list[int]

정렬할 정수 list

required

Returns:

Type Description
list[int]

오름차순으로 정렬된 list

Examples:

>>> zz.algorithm.merge_sort([64, 34, 25, 12, 22, 11, 90])
[11, 12, 22, 25, 34, 64, 90]
Source code in zerohertzLib/algorithm/sort.py
def merge_sort(arr: list[int]) -> list[int]:
    """Merge Sort Algorithm: 분할 정복 방법을 사용하여 배열을 절반으로 나누고, 각 부분을 정렬한 다음 합치는 방식으로 정렬

    Args:
        arr: 정렬할 정수 list

    Returns:
        오름차순으로 정렬된 list

    Examples:
        >>> zz.algorithm.merge_sort([64, 34, 25, 12, 22, 11, 90])
        [11, 12, 22, 25, 34, 64, 90]
    """
    if len(arr) > 1:
        mid = len(arr) // 2
        left = arr[:mid]
        right = arr[mid:]
        merge_sort(left)
        merge_sort(right)
        i = j = k = 0
        while i < len(left) and j < len(right):
            if left[i] < right[j]:
                arr[k] = left[i]
                i += 1
            else:
                arr[k] = right[j]
                j += 1
            k += 1
        while i < len(left):
            arr[k] = left[i]
            i += 1
            k += 1
        while j < len(right):
            arr[k] = right[j]
            j += 1
            k += 1
    return arr

quick_sort

quick_sort(arr: list[int]) -> list[int]

Quick Sort Algorithm: Pivot을 선택하여 이보다 작은 요소는 왼쪽, 큰 요소는 오른쪽에 위치시키는 방식으로 분할 정복을 사용하여 정렬

Parameters:

Name Type Description Default
arr list[int]

정렬할 정수 list

required

Returns:

Type Description
list[int]

오름차순으로 정렬된 list

Examples:

>>> zz.algorithm.quick_sort([64, 34, 25, 12, 22, 11, 90])
[11, 12, 22, 25, 34, 64, 90]
Source code in zerohertzLib/algorithm/sort.py
def quick_sort(arr: list[int]) -> list[int]:
    """Quick Sort Algorithm: Pivot을 선택하여 이보다 작은 요소는 왼쪽, 큰 요소는 오른쪽에 위치시키는 방식으로 분할 정복을 사용하여 정렬

    Args:
        arr: 정렬할 정수 list

    Returns:
        오름차순으로 정렬된 list

    Examples:
        >>> zz.algorithm.quick_sort([64, 34, 25, 12, 22, 11, 90])
        [11, 12, 22, 25, 34, 64, 90]
    """
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quick_sort(left) + middle + quick_sort(right)

radix_sort

radix_sort(arr: list[int]) -> list[int]

Radix Sort Algorithm: 각 자릿수에 대해 개별적으로 정렬

Parameters:

Name Type Description Default
arr list[int]

정렬할 정수 list

required

Returns:

Type Description
list[int]

오름차순으로 정렬된 list

Examples:

>>> zz.algorithm.radix_sort([64, 34, 25, 12, 22, 11, 90])
[11, 12, 22, 25, 34, 64, 90]
Source code in zerohertzLib/algorithm/sort.py
def radix_sort(arr: list[int]) -> list[int]:
    """Radix Sort Algorithm: 각 자릿수에 대해 개별적으로 정렬

    Args:
        arr: 정렬할 정수 list

    Returns:
        오름차순으로 정렬된 list

    Examples:
        >>> zz.algorithm.radix_sort([64, 34, 25, 12, 22, 11, 90])
        [11, 12, 22, 25, 34, 64, 90]
    """
    max_val = max(arr)
    exp = 1
    while max_val / exp > 0:
        _counting_sort_for_radix(arr, exp)
        exp *= 10
    return arr

selection_sort

selection_sort(arr: list[int]) -> list[int]

Selection Sort Algorithm: 배열에서 가장 작은 값을 찾아 해당 값을 배열의 앞부분으로 이동시키는 방식으로 정렬

Parameters:

Name Type Description Default
arr list[int]

정렬할 정수 list

required

Returns:

Type Description
list[int]

오름차순으로 정렬된 list

Examples:

>>> zz.algorithm.selection_sort([64, 34, 25, 12, 22, 11, 90])
[11, 12, 22, 25, 34, 64, 90]
Source code in zerohertzLib/algorithm/sort.py
def selection_sort(arr: list[int]) -> list[int]:
    """Selection Sort Algorithm: 배열에서 가장 작은 값을 찾아 해당 값을 배열의 앞부분으로 이동시키는 방식으로 정렬

    Args:
        arr: 정렬할 정수 list

    Returns:
        오름차순으로 정렬된 list

    Examples:
        >>> zz.algorithm.selection_sort([64, 34, 25, 12, 22, 11, 90])
        [11, 12, 22, 25, 34, 64, 90]
    """
    for i, _ in enumerate(arr):
        min_idx = i
        for j in range(i + 1, len(arr)):
            if arr[min_idx] > arr[j]:
                min_idx = j
        arr[i], arr[min_idx] = arr[min_idx], arr[i]
    return arr

soe

soe(n_max: int) -> list[int]

Sieve of Eratosthenes

Parameters:

Name Type Description Default
n_max int

구하고자 하는 소수 범위의 최댓값

required

Returns:

Type Description
list[int]

N까지 존재하는 소수 list

Examples:

>>> zz.algorithm.soe(10)
[2, 3, 5, 7]
Source code in zerohertzLib/algorithm/prime.py
def soe(n_max: int) -> list[int]:
    """Sieve of Eratosthenes

    Args:
        n_max: 구하고자 하는 소수 범위의 최댓값

    Returns:
        N까지 존재하는 소수 list

    Examples:
        >>> zz.algorithm.soe(10)
        [2, 3, 5, 7]
    """
    visited = [False, False] + [True] * (n_max - 1)
    prime_numbers = []
    for i in range(2, n_max + 1):
        if visited[i]:
            prime_numbers.append(i)
            for idx in range(2 * i, n_max + 1, i):
                visited[idx] = False
    return prime_numbers