Computer Science/자료 구조, 알고리즘

시간복잡도/공간복잡도/점근표기법

JM Lee 2023. 5. 1. 18:56
728x90

작년 학교 강의를 통해서 알고리즘을 조금 찍먹만 해보았지만,

이 3가지 개념은 정말 수업 내내 나타났기 때문에 이번에는 제대로 공부하고 정리해보았다.

 

시간 복잡도 개념

시간 복잡도란? : 알고리즘이 문제를 풀기 위한 시간(혹은 연산)을 말한다.

단어로 말하자면 "수행시간"

 

우리가 프로그래머스에서 문제를 풀 때 문제를 해결하는 시간이 아래에 뜨는데,

이것이 시간복잡도를 간접적으로 나타내어 준다.

테스트 1의 0.03ms가 내 코드의 시간복잡도이다.

참고로 옆의 10.2MB는 공간복잡도!

 

 

시간 복잡도 풀이법

그렇다면 이 시간복잡도는 어떤 방식으로 구하는 걸까?

 

아래의 예시를 보면 금방 이해될 것이다.

    for num in array:              # array 의 길이(N)만큼 아래 연산이 실행
        for compare_num in array:  # array 의 길이(N)만큼 아래 연산이 실행
            if num < compare_num:  # 비교 연산 1번 실행
                break
        else:
            return num
            
# 연산 과정(시간 복잡도): array의 길이 * array의 길이 * 비교 연산
# == N*N*1 
# == N**2

또 다른 풀이로도 계산해보면

max_num = array[0]     # 연산 1번 실행
for num in array:      # array 의 길이만큼 아래 연산이 실행
	if num > max_num:  # 비교 연산 1번 실행
		max_num = num  # 대입 연산 1번 실행
                
                
# max_num 대입 연산 + {array의 길이 X (비교 연산 1번 + 대입 연산 1번)}
# == 1 + N * 2
# == 2N + 1

각각 (N제곱)과 (2N+1)로 복잡도가 나온다.

그럼 우리는 더 빠른 방법으로 문제를 해결해야 하는데, 어떤 식이 더 빨리 풀릴까?

처음에나 왼쪽이 근소하게 유리했지, N의 숫자가 커질수록 2N+1이 압도적으로 시간에 있어 유리함을 알 수 있다.

 

이 식을 통해 느끼는 것은

변수 N 앞에 붙는 상수들은 아무런 의미가 없다.

2N이나 2N+1이나 N의 숫자가 커질 때는 무의미한 차이(점점 차지하는 비중이 0%에 수렴하게 됨)이기 때문에

비교를 할 때 순서는

1. 제곱 여부 > 2. 계수 여부 (ex) 2N, 5N) > 3. 상수

사실상 제곱 여부만 보면 된다! 2번과 3번은 사실상 무의미

공간복잡도

 

공간복잡도란? : 프로그램의 성능을 분석하는 방법 중 하나로,

                         작성한 프로그램이 얼마나 많은 공간(메모리)을 차지하느냐를 분석하는 방법

최근에 좋은 메모리가 많이 등장해서 중요도가 크게 줄었다지만, 그래도 알아두면 좋다.

 

아래 함수에서 메모리를 차지하는 것으로는 어떤 것이 있을까?

def find_max_occurred_alphabet(string):
    alphabet_array = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "x", "y", "z"]
    max_occurrence = 0
    max_alphabet = alphabet_array[0]

    for alphabet in alphabet_array:
        occurrence = 0
        for char in string:
            if char == alphabet:
                occurrence += 1

        if occurrence > max_occurrence:
            max_alphabet = alphabet
            max_occurrence = occurrence

    return max_alphabet

result = find_max_occurred_alphabet
print("정답 = a 현재 풀이 값 =", result("Hello my name is sparta"))
print("정답 = a 현재 풀이 값 =", result("Sparta coding club"))
print("정답 = s 현재 풀이 값 =", result("best of best sparta"))

바로 다음과 같은 것들이 메모리를 차지한다고 볼 수 있다.

(코드블럭 내부에는 밑줄이나 글씨 굵기 조절 못 하는걸까..)

alphabet_array = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "x", "y", "z"]
	# -> 26 개의 공간을 사용합니다
max_occurrence = 0 # 1개의 공간을 사용합니다
max_alphabet = alphabet_array[0]   # 1개의 공간을 사용합니다.

for alphabet in alphabet_array:
    occurrence = 0  # 1개의 공간을 사용합니다

 

공간복잡도의 효율성 비교도 시간복잡도와 마찬가지로 따진다.

 

점근 표기법

 

점근표기법 : 어떤 함수의 증가 양상을 다른 함수와의 비교로 표현하는 수론과 해석학의 방법

                     알고리즘의 성능을 수학적으로 표기하여 알고리즘의 효율성을 따지는 데 쓰이는 표기법.

 

빅오 표기법 : 최악의 경우에 어느 정도의 연산량이 나오는가?(시간복잡도의 최댓값)

빅오메가 표기법 : 최선의 경우에 어느 정도의 연산량이 나오는가?(시간복잡도의 최솟값)

 

대부분의 경우에서 우리는 최악의 경우를 대비해야 하기 때문에 주로 빅오 표기법을 사용

 

빅오의 시간복잡도는 다음과 같다.

f(n) = O(g(n))

 

빅오 표기법의 특징은 다음과 같다.

1. 최고차항만 표기 2. 계수 무시 3. 상수 무시

위에서 말한 것처럼, 시간복잡도에 영향력이 0에 수렴하는 계수와 상수는 무시하는 것이다.

이에 따라 시간복잡도가 O(4N^3+6N^2+N+5) 일 경우, O(N^3)으로 표기한다.

'Computer Science > 자료 구조, 알고리즘' 카테고리의 다른 글

버블 정렬  (0) 2023.08.17
해쉬(Hash)  (0) 2023.06.01
스택(stack) / 큐(queue)  (0) 2023.05.21
배열과 리스트  (0) 2023.05.20
컴퓨터 구조와 운영체제 핵심 개념  (0) 2023.05.19