Study/Tech Interview

Algorithm - Sorting Algorithm, 반복문과 재귀 함수

by somida 2021. 5. 18.
반응형

Algorithm

어떠한 문제를 해결하기 위해 정해진 일련의 절차나 방법

 

Sorting Algorithm

Sorting
Algorithm
공간 복잡도 시간 복잡도 Stable
최악 최선 평균 최악
Bubble Sort O(1) O(n) O(n^2) O(n^2) O
Selection Sort O(1) O(n^2) O(n^2) O(n^2) X
Insert Sort O(1) O(n) O(n^2) O(n^2) O
Merge Sort O(n) O(nlogn) O(nlogn) O(nlogn) O
Quick Sort O(1) O(nlogn) O(nlogn) O(n^2) X
Heap Sort O(1) O(n) O(nlogn) O(nlogn) X

 

Bubble Sort와 Selection Sort

  • Bubble Sort와 Selection Sort 둘 다 최악의 시간 복잡도는 O(n^2)을 가지지만, 버블 정렬은 처음부터 정렬된 배열이 들어오게 되면 1회전만 진행하기 때문에 O(n)의 시간 복잡도를 가질 수 있음
  • 하지만, Selection Sort는 정렬을 위한 비교 횟수는 동일하게 많지만, 실제로 교환을 행하는 횟수는 적기 때문에 조금 더 빠르다는 장점을 가지고 있음
  • Bubble Sort는 인접한 요소끼리 서로의 값을 비교하기 때문에 중복된 값의 순서가 변하지 않는 Stable 한 알고리즘이고, Selection Sort는 모든 요소를 탐색한 후에 마지막 최솟값과 변경시키기 때문에 Unstable 한 알고리즘

 

Merge Sort와 Quick Sort

  • Merge Sort는 분할 후 병합 시점에서 정렬을 실행하는 과정이고, Quick Sort는 Pivot을 기준으로 분할하는 시점에서 정렬을 진행하는 과정
  • Merge Sort는 Stable정렬에 속하고, Quick Sort는 Unstable 정렬에 속함

 

 

Factorial

반복문

def factorial(num):
    result = 1
    for i in range(1, num + 1):
        result *= i
    return result

재귀

def factorial(num):
    if num == 1:
        return 1
    return num * factorial(num - 1)

라이브러리

from math import factorial
print(factorial(5))

 

반복문과 재귀 함수

  • 반복문
    • 명령을 반복적으로 실행시키는 것으로 설정한 조건에 도달할 때까지 반복 실행
    • 제어 조건이 참일 경우 무한 반복이 발생
    • 재귀 함수보다 속도가 빠른 편
    • 코드의 길이가 길어지고 변수가 늘어나서 가독성이 좋지 않음
  • 재귀 함수
    • 함수 자체를 계속해서 호출하는 것으로 재귀를 호출하지 않고 함수를 return 시킬 때까지 반복 실행
    • 조건에 수렴하지 않을 경우 무한 재귀가 발생해 스텍 메모리를 초과하는 Stack Overflow가 발생함
    • 반복문에 비해 속도가 느린 편
    • 코드의 길이와 변수가 적다는 장점으로 가독성이 높음
    • Stack Overflow를 방지하기 위해 꼬리 재귀를 사용하기도 함(단, 컴파일러가 최적화를 지원해야 가능)
Stack Overflow
Stack영역의 메모리가 지정된 범위를 벗어날 때 발생
함수를 호출하면 함수의 지역변수, 리턴 값, 주소 값 등이 스택에 저장이 되는데,
재귀 함수를 통해 반복적으로 함수를 호출하게 되면, Stack메모리를 초과하는 현상을 Stack Overflow라고 함

꼬리 재귀(Tail Call Recursion)
꼬리 재귀는 함수 호출을 위한 파라미터의 연산이 일어나는 장소의 차이를 가짐
즉, Return문에 연산이 존재하는지의 차이점
# 일반 재귀
def factorial(num):
    if num == 1:
        return 1
    return num * factorial(num - 1)
    
# 꼬리 재귀
def factorial(num, ans):
    if num == 1
        return ans
    return factorial(num - 1, ans * num)​

꼬리 재귀는 연산이 return문 이전에 발생해 다음 함수 호출 시에 결과만을 전달한다.
이 과정에서 컴파일러가 꼬리 재귀를 최적화하는 과정에서 반복문으로 변경하게 되면서 기존 재귀의 메모리와 성능에 대한 문제를 감소시킬 수 있음 

 

피보나치 수열

반복문

def fibo(num):
    a, b = 1, 1
    if num == 1 or num == 2:
        return 1
    for i in range(1, num):
        a, b = b, a + b
    return a

재귀

def fibo(num):
    if num == 1 or num == 2:
        return 1
    return fibo(num - 1) + fibo(num - 2)

DP

def fibo(num):
    dp = []
	for i in range(num):
    	if i < 2:
        	dp.append(1)
    	else:
        	dp.append(dp[i-2] + dp[i-1])
	return dp

 


References

 

정렬 알고리즘 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 컴퓨터 과학과 수학에서 정렬 알고리즘(sorting algorithm)이란 원소들을 번호순이나 사전 순서와 같이 일정한 순서대로 열거하는 알고리즘이다. 효율적인 정렬은

ko.wikipedia.org

 

반응형

'Study > Tech Interview' 카테고리의 다른 글

Database 면접  (0) 2021.05.22
Algorithm - Two Pointer, 순열과 조합, 최소 공배수와 최대 공약수  (0) 2021.05.21
Algorithm - Heap Sort  (0) 2021.05.18
Algorithm - Quick Sort  (0) 2021.05.17
Algorithm - Merge Sort  (0) 2021.05.17

댓글