본문 바로가기

컴퓨터 과학/알고리즘

(14)
[알고리즘] 정렬 알고리즘 정리 (시간 복잡도, 공간 복잡도, 안정성) 이 외에도 쉘 정렬, 선택 정렬, 도수 정렬 등이 있다.
[알고리즘] 쉘 정렬 쉘 정렬은 하나의 배열을 여러 개로 쪼개 각각 정렬하는 과정을 반복한 후, 마지막으로 한 번에 정렬하는 기법이다. 이 때, 특정 간격으로 떨어진 요소들을 모아 정렬하는 것이 특징이다. 다음 그림에서는 4칸씩 떨어진 2개의 요소들을 정렬하는 경우를 보여준다. 즉, (8, 7), (1, 6), (4, 3), (2, 5)를 각각 정렬한다. 그 후 2칸씩 떨어진 요소 4개씩, 즉 (7, 3, 8, 4), (1, 2, 6, 5)를 묶어 각각 정렬한다. 그러면 전체 배열은 최종적으로 (3, 4, 7, 8, 1, 2, 5, 6)이 되며, 최종적으로 이를 단순 삽입 정렬하면 된다. 세 번의 정렬 과정에서, 기준 간격은 4 -> 2 -> 1로 변한다. 그런데 이와 같이 간격들이 서로 배수가 되면, 이미 정렬한 원소들을 ..
[알고리즘] 8퀸 문제 (재귀) 8 * 8 크기의 체스판에 8개의 퀸을 배치하는 경우의 수를 생각해 보자. 각 행과 열, 대각선에서 퀸이 2개 있으면 안 된다. ex) □ □ ■ □ □ □ □ □ □ □ □ □ □ ■ □ □ □ □ □ □ □ □ □ ■ ■ □ □ □ □ □ □ □ □ □ □ □ ■ □ □ □ □ □ □ □ □ □ ■ □ □ ■ □ □ □ □ □ □ □ □ □ ■ □ □ □ □ 이 소스 코드에서 문제를 푸는 방식은 다음과 같다. 0열 ~ 7열까지 퀸을 순서대로 배치하되, 배치하려는 행과 대각선에 다른 퀸이 있는지를 확인한다. # 8퀸 문제 알고리즘 구현하기 pos = [0] * 8 # 각 열에 배치한 퀸의 위치 flag_a = [False] * 8 # 각 행에 퀸을 배치했는지 체크 flag_b = [False] * 15..
[알고리즘] 단순 삽입 정렬 * 출처: 알고리즘 교재 p240 ~ p243 1. 단순 삽입 정렬이란? 아직 정렬되지 않은 부분의 맨 앞 원소를, 정렬된 부분의 알맞은 위치에 삽입하는 알고리즘이다. 2. 특징 1) 서로 떨어져 있는 원소를 교환하지 않으므로 안정적이다. 2) 시간 복잡도는 O(N^2)이다. 3. 소스 코드 # 단순 삽입 정렬 알고리즘 구현하기 from typing import MutableSequence def insertion_sort(a: MutableSequence) -> None: """단순 삽입 정렬""" n = len(a) for i in range(1, n): j = i # j : 1 ~ 6 tmp = a[i] # tmp : a[1] ~ a[6] while j > 0 and a[j - 1] > tmp: a..
[알고리즘] 버블 정렬 버블 정렬은, 배열 내 이웃한 원소들을 비교함으로써 정렬하는 알고리즘이다. 어느 배열 a가 n개의 원소를 가진다면, a[n - 1]과 a[n - 2], ... , a[1]과 a[0]을 순차적으로 비교한다. 버블 정렬은 안정적인 알고리즘이며, 시간 복잡도는 O(N^2)이다. (교재 p224 참고) # 버블 정렬 알고리즘 구현하기 from typing import MutableSequence def bubble_sort(a: MutableSequence) -> None: """버블 정렬""" n = len(a) for i in range(n - 1): # i의 범위: 0 ~ n - 2 for j in range(n - 1, i, -1): # 11 ~ 13행: Pass 과정 if a[j - 1] > a[j]:..
[알고리즘] 단순 선택 정렬 단순 선택 정렬은 가장 작은 원소를 골라 인덱스 0에, 두 번째로 작은 원소를 골라 인덱스 1에, ... 배치하는 방법이다. 이 알고리즘은 안정적이지 않으며, 시간 복잡도는 O(N^2)이다. (교재 p239 참고) # 단순 선택 정렬 알고리즘 구현하기 from typing import MutableSequence def selection_sort(a: MutableSequence) -> None: """단순 선택 정렬""" n = len(a) for i in range(n - 1): print(f'i = {i}') min = i # i = 0, 1, 2, 3, 4, 5 for j in range(i + 1, n): # j = [1, 2, 3, 4, 5, 6], ... , [5, 6], [6] if a[j..
[알고리즘] 브루트 포스법 브루트 포스법은 어떤 문자열에서 특정한 패턴을 찾을 때까지 일일히 문자를 대조해 보는 알고리즘이다. 당연히 연산 횟수가 무지막지하게 많으며, 일반적으로 시간 복잡도는 O(M * N)으로 알려저 있다. (패턴의 길이: M, 텍스트의 길이: N) # 브루트 포스법으로 문자열 검색하기 def bf_match(txt: str, pat: str) -> int: """브루트 포스법으로 문자열 검색""" pt = 0 # txt를 따라가는 커서 pp = 0 # pat를 따라가는 커서 while pt != len(txt) and pp != len(pat): if txt[pt] == pat[pp]: pt += 1 pp += 1 else: pt = pt - pp + 1 pp = 0 return pt - pp if pp ==..
[알고리즘] {재귀} 하노이 탑 * 참고 : Do It! 자료구조와 함께 배우는 알고리즘 파이썬 편 p200 ~ p203 하노이 탑에는 3개의 기둥(A, B, C)가 있고, 기둥 A에는 위에서부터 차례대로 '원반 1, 원반 2, ... , 원반 n - 1, 원반 n'이 있다. 이 n개의 원반들을 모두 C기둥으로 옮겨야 하며, 최적의 방식은 다음과 같다. 1) 기둥 A의 원반 1, ... , 원반 n - 1들을 기둥 B로 옮긴다. 2) 기둥 A의 원반 n을 기둥 C로 옮긴다. 3) 기둥 B의 원반 1, ... , 원반 n - 1들을 기둥 C로 옮긴다. 그런데 과정 1 & 3 또한 여러 개의 원반들을 다른 기둥으로 옮기는 행위이기 때문에, 다시 재귀적으로 과정 1, 2, 3을 사용할 수 있다. 단지 시작 기둥, 중간 기둥, 목표 기둥이 달..