알고리즘

공간 복잡도 판단하기

na_o 2021. 8. 13. 19:13
728x90

[공간 복잡도란?]

입력값과 문제를 해결하는 데 걸리는 공간과의 상관관계

(공간은 변수나 배열 등 값을 담을 때 쓰이는 것들을 말함)

"우리는 공간이 적게 걸리는 알고리즘을 좋아하니

 입력값이 늘어나도 걸리는 공간이 덜 늘어나는 알고리즘이 좋은 알고리즘이겠죠?"

 


[최빈값 찾기 알고리즘의 공간 복잡도 판단해보기]

방법1) 

각 알파벳마다 문자열들을 돌면서 몇 글자가 나왔는 지 확인

만약 그 숫자가 저장한 알파벳 빈도 수보다 크면, 그 값을 저장하고 제일 큰 알파벳으로 저장.

def find_max_occurred_alphabet(string):
    # alphabet_array: 26 개의 공간을 사용합니다
    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                    # 1개의 공간을 사용합니다
    max_alphabet = alphabet_array[0]      # 1개의 공간을 사용합니다

    for alphabet in alphabet_array:       
        occurrence = 0                    # 1개의 공간을 사용합니다
        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"))

저장하는 데이터 양이 1개의 공간을 사용한다고 계산하면 됨!!

1. alphabet_array의 공간 26개

2. max_occurence, max_alphabet, occurence 변수 총 3개

총 29

29만큼의 공간이 필요!

결론) 위의 함수는 29만큼의 공간이 사용되었구나 라고 할 수 있음

 

 

방법2)

각 알파벳의 빈도수를 배열에 저장한 다음, 빈도수 중 가장 많은 알파벳의 인덱스 값을 반환

def find_max_occurred_alphabet(string):
    alphabet_occurrence_list = [0] * 26             # 26 개의 공간을 사용합니다

    for char in string:
        if not char.isalpha():
            continue
        arr_index = ord(char) - ord('a')            # 1개의 공간을 사용합니다
        alphabet_occurrence_list[arr_index] += 1

    max_occurrence = 0                              # 1개의 공간을 사용합니다
    max_alphabet_index = 0                          # 1개의 공간을 사용합니다
    for index in range(len(alphabet_occurrence_list)):
        alphabet_occurrence = alphabet_occurrence_list[index] # 1개의 공간을 사용합니다
        if alphabet_occurrence > max_occurrence:
            max_occurrence = alphabet_occurrence
            max_alphabet_index = index

    return chr(max_alphabet_index + ord('a'))


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"))

1. alphabet_array의 길이 26

2. arr_index, max_occurence, max_alphabet_index, alphabet_occurence 변수 총 4

총 30

결론) 이 함수는 30만큼의 공간이 사용되었구나 라고 할 수 있음

 

 

공간을 더 적게 쓴 첫 번째 방법이 더 효율적인가요?!!??!!!

29와 30 모두 상수이기 때문에 큰 상관이 없음!

대부분의 문제에서는 알고리즘의 성능이 공간에 의해서 결정되지 않음

공간복잡도보다는 시간복잡도를 더 신경써야 함!!


방법1)

각 알파벳마다 문자열들을 돌면서 몇 글자가 나왔는 지 확인

만약 그 숫자가 저장한 알파벳 빈도 수보다 크면, 그 값을 저장하고 제일 큰 알파벳으로 저장.

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:     # alphabet_array 의 길이(26)만큼 아래 연산이 실행
        occurrence = 0                  # 대입 연산 1번 실행
        for char in string:             # string 의 길이(N)만큼 아래 연산이 실행
            if char == alphabet:        # 비교 연산 1번 실행
                occurrence += 1         # 대입 연산 1번 실행

        if occurrence > max_occurrence: # 비교 연산 1번 실행
            max_alphabet = alphabet     # 대입 연산 1번 실행
            max_occurrence = occurrence # 대입 연산 1번 실행

    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"))

 

1. alphabet_array 의 길이 X 대입 연산 1번

2. alphabet_array 의 길이 X string의 길이 X (비교 연산 1번 + 대입 연산 1번)

3. alphabet_array 의 길이 X (비교 연산 1번 + 대입 연산 2번)

만큼의 시간이 필요!

26 * (1 + 2 * N + 3) = 52N + 104

위의 함수는 52N + 104 만큼의 시간이 걸렸다고 말할 수 있음

하지만 배수나 상수 등 숫자는 별 의미가 없으니까 제외하면

 

결론) N만큼의 시간이 걸렸다고 하면 됨!

 

 

방법2)

각 알파벳의 빈도수를 배열에 저장한 다음, 빈도수 중 가장 많은 알파벳의 인덱스 값을 반환

def find_max_occurred_alphabet(string):
    alphabet_occurrence_list = [0] * 26

    for char in string:                             # string 의 길이만큼 아래 연산이 실행
        if not char.isalpha():                      # 비교 연산 1번 실행
            continue
        arr_index = ord(char) - ord('a')            # 대입 연산 1번 실행 
        alphabet_occurrence_list[arr_index] += 1

    max_occurrence = 0                              # 대입 연산 1번 실행 
    max_alphabet_index = 0                          # 대입 연산 1번 실행 
    for index in range(len(alphabet_occurrence_list)):        # alphabet_array 의 길이(26)만큼 아래 연산이 실행 
        alphabet_occurrence = alphabet_occurrence_list[index] # 대입 연산 1번 실행 
        if alphabet_occurrence > max_occurrence:              # 비교 연산 1번 실행
            max_occurrence = alphabet_occurrence              # 대입 연산 1번 실행
            max_alphabet_index = index                        # 대입 연산 1번 실행

    return chr(max_alphabet_index + ord('a'))


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"))

1. string의 길이 * (비교 연산 1번 + 대입 연산 2번)

2. 대입 연산 2번

3. alphabet_array의 길이 * (비교 연산 1번 + 대입 연산 3번)

만큼이 시간이 필요

N * (1 + 2) + 2 + 26 * (1 + 3) = 3N + 106

3N + 106 만큼의 시간이 걸렸다 라고 할 수 있음

하지만 상수는 제외해도 되니까

 

결론) 만큼의 시간이 필요하다라고 말할 수 있음

 

N의 길이 52N + 104 3N + 106 N^2
1 156 109 1
10 624 136 100
100 5304 406 10000
1000 52104 3106 1000000
52N+104든 3N+106이든 N^2에 비해서 아무것도 아니구나!!

 

 

 

공간복잡도보다 시간복잡도를 더 신경써야 한다..!!!

공간을 희생해서라도 시간복잡도를 최대한 좋게 만드는 것을 고민해야한다

'알고리즘' 카테고리의 다른 글

알고리즘 더 풀어보기 (1)  (0) 2021.08.17
점근 표기법  (0) 2021.08.15
시간 복잡도 판단하기  (0) 2021.08.11
알고리즘과 친해지기 - 최빈값 찾기  (0) 2021.08.10
알고리즘과 친해지기 - 최대값 찾기  (0) 2021.08.09