Published on

알고리즘 시간복잡도 완벽 가이드

Authors
  • avatar
    Name
    devnmin
    Twitter

알고리즘 시간복잡도: 효율적인 코드를 위한 필수 개념 ⏱️

안녕하세요! 오늘은 알고리즘 학습에서 가장 기초가 되는 시간복잡도(Time Complexity) 에 대해 자세히 알아보겠습니다. 코딩 테스트나 실제 개발에서 꼭 필요한 개념이니 차근차근 살펴볼게요!

1. 시간복잡도란? 🤔

시간복잡도는 알고리즘의 성능을 나타내는 척도입니다. 입력 크기가 증가할 때 알고리즘의 실행 시간이 어떻게 증가하는지를 표현하는 지표예요.

왜 시간복잡도를 알아야 할까요?

  1. 성능 예측: 프로그램이 얼마나 빨리 실행될지 예측할 수 있습니다.
  2. 최적화: 더 효율적인 알고리즘을 선택할 수 있습니다.
  3. 코딩 테스트: 문제 해결 시 시간 제한을 고려할 수 있습니다.

2. Big-O 표기법 📈

Big-O 표기법은 알고리즘의 최악의 경우 시간복잡도를 표현하는 방법입니다.

주요 시간복잡도 종류

  1. O(1) - 상수 시간
    • 입력 크기와 관계없이 항상 같은 시간 소요
    • 예: 배열의 첫 번째 요소 접근
def get_first(arr):
   return arr[0] # O(1)
  1. O(log n) - 로그 시간
    • 입력이 커져도 실행 시간이 조금씩만 증가
    • 예: 이진 탐색
[16개 요소가 있는 배열에서의 이진 탐색 과정]

Level 1:      8
            /   \          # 첫 번째 비교 후 절반으로 나눔
Level 2:    4     12
           / \   /  \      # 두 번째 비교 후 다시 절반으로
Level 3:  2   6 10   14
         / \ / \ / \  / \  # 세 번째 비교 후 다시 절반으로
Level 4: 1 3 5 7 9 11 13 15

- 16개의 요소를 4번의 비교로 찾을 수 있음
- 일반화: n개의 요소는 log₂n번의 비교로 찾을 수 있음

예를 들어, 크기가 16인 정렬된 배열에서 특정 값을 찾을 때:

  1. 첫 비교: 16개 → 8개 (절반으로 감소)
  2. 두 번째: 8개 → 4개
  3. 세 번째: 4개 → 2개
  4. 네 번째: 2개 → 1개

따라서 시간복잡도는 O(log n)이 됩니다.

수식으로는: log₂16 = 4

배열 크기(n)최대 비교 횟수
21 (log₂2)
42 (log₂4)
83 (log₂8)
164 (log₂16)
325 (log₂32)
102410 (log₂1024)

이처럼 데이터가 2배로 증가해도 비교 횟수는 1회만 증가하는 매우 효율적인 시간복잡도를 가집니다.

  1. O(n) - 선형 시간
    • 입력 크기에 비례하여 시간이 증가
    • 예: 배열 순회
def linear_search(arr, target):
   for i in range(len(arr)): # O(n)
      if arr[i] == target:
      return i
   return -1
  1. O(n log n) - 선형 로그 시간
    • 대부분의 효율적인 정렬 알고리즘의 시간복잡도
    • 예: 병합 정렬, 퀵 정렬
def merge_sort(arr):
   if len(arr) <= 1:
      return arr

   mid = len(arr) // 2
   left = merge_sort(arr[:mid])
   right = merge_sort(arr[mid:])

   return merge(left, right) # O(n log n)
  1. O(n^2) - 제곱 시간
    • 입력 크기의 제곱에 비례하여 시간이 증가
    • 예: 브루투포스 탐색, 이중 반복문, 버블 정렬
def bubble_sort(arr):
   n = len(arr)
   for i in range(n): # O(n²)
      for j in range(n-1):
         if arr[j] > arr[j+1]:
            arr[j], arr[j+1] = arr[j+1], arr[j]
  1. O(2^n) - 지수 시간
    • 입력 크기가 증가할수록 시간이 기하급수적으로 증가
    • 예: 피보나치 수열
def fibonacci(n):
   if n <= 1:
      return n
   return fibonacci(n-1) + fibonacci(n-2) # O(2^n)

3. 실전에서의 시간복잡도 활용 💡

입력 크기별 제한 시간 가이드

시간복잡도1초 안에 처리 가능한 최대 입력 크기
O(1)제한 없음
O(log n)2¹⁰⁰⁰ 이상
O(n)약 1억 (10⁸)
O(n log n)약 500만
O(n²)약 10,000
O(2ⁿ)약 20

Python 코드 실행 시 주의사항

  1. Python은 다른 언어보다 느립니다
  2. 일반적으로 1초에 2천만 번의 연산이 가능합니다
  3. 시간 제한이 1초라면 위 표의 값보다 작게 설정하는 것이 안전합니다

4. 시간복잡도 최적화 전략 🔧

1. 적절한 자료구조 선택

작업최적의 자료구조시간복잡도
검색해시맵O(1)
정렬정렬된 배열O(n log n)
최소/최대값O(log n)

2. 알고리즘 최적화 팁

  1. 불필요한 반복문 제거

    • 중첩 반복문을 피하기
    • 가능한 한 번의 순회로 해결하기
  2. 공간복잡도와의 트레이드오프

    • 메모리를 더 사용해서 시간을 줄일 수 있는지 검토
    • 캐싱이나 메모이제이션 활용
  3. 입력 크기에 따른 전략

    • 작은 입력: 단순한 알고리즘도 충분
    • 큰 입력: 효율적인 알고리즘 필수

5. 코딩 테스트 실전 팁! 💪

  1. 문제 분석 단계

    • 입력 크기 확인하기
    • 시간 제한 확인하기
    • 필요한 시간복잡도 추정하기
  2. 구현 단계

    • 가장 단순한 해결책부터 시작
    • 필요한 경우 최적화
    • 극단적인 케이스 고려
  3. 테스트 단계

    • 경계값 테스트
    • 시간 초과 가능성 체크
    • 메모리 사용량 확인

마무리 🎯

시간복잡도는 알고리즘의 효율성을 측정하는 중요한 척도입니다. 실제 개발이나 코딩 테스트에서 시간복잡도를 고려하는 것은 필수적이에요. 이 글에서 배운 내용을 바탕으로 더 효율적인 코드를 작성하시길 바랍니다!

더 자세한 내용이나 특정 알고리즘의 시간복잡도에 대해 궁금하신 점이 있다면 댓글로 남겨주세요. 함께 성장하는 개발자가 되어봐요! 🚀

Big-O Complexity Chart
색상시간복잡도설명
파란색O(1)상수 시간
초록색O(log n)로그 시간
검정색O(n)선형 시간
보라색O(n log n)선형 로그 시간
빨간색O(n²)이차 시간
하늘색O(2ⁿ)지수 시간