안녕하세요! 이번 포스트에서는 자바 코딩테스트에서 자주 다루어지는 시간 복잡도 표기법에 대해 알아보도록 하겠습니다. 알고리즘 문제를 풀기 위해서는 시간 복잡도를 이해하는 것이 매우 중요합니다. 시간을 절약하기 위해서는 어떤 알고리즘이 더 효율적인지를 판단하는 능력이 필요합니다. 그래서, 이에 대한 이해를 돕기 위해 예제를 통해 접근해보겠습니다.
문제 설명
먼저, 알고리즘 문제를 소개하겠습니다.
문제: 두 수의 합
주어진 정수 배열 nums
와 정수 target
가 있을 때, 배열에 두 수의 합이 target
이 되는 인덱스를 찾으세요. 임의의 정수의 조합을 고려하지 않습니다. 각 입력에 정확히 하나의 해답이 있다고 가정하며, 같은 요소를 두 번 사용할 수 없습니다. 함수의 반환값은 두 인덱스의 배열입니다. 예를 들어:
입력: nums = [2, 7, 11, 15], target = 9 출력: [0, 1] 설명: nums[0] + nums[1] = 2 + 7 = 9이므로 출력은 [0, 1]입니다.
문제 풀이 과정
1단계: 문제 분석
이 문제는 두 수를 찾아 합이 target
이 되는 것을 찾는 문제입니다. 이 문제는 배열의 길이에 따라 다양한 접근 방식으로 풀 수 있지만, 가장 기초적인 방법은 중첩 for 문을 사용하는 방법입니다.
2단계: 중첩 for 문을 통한 접근
단순하게 두 개의 수를 찾기 위해 각 요소에 대해 나머지 모든 요소를 확인할 것입니다. 이렇게 하면, 경우의 수가 n(n-1)/2
만큼 발생하여, 시간 복잡도가 O(n2)
가 됩니다.
public int[] twoSum(int[] nums, int target) { for (int i = 0; i < nums.length; i++) { for (int j = i + 1; j < nums.length; j++) { if (nums[i] + nums[j] == target) { return new int[] {i, j}; } } } throw new IllegalArgumentException("No two sum solution"); }
3단계: 시간 복잡도 분석
위의 알고리즘은 O(n2)의 시간 복잡도를 요구합니다. 이렇게 높은 시간 복잡도를 가진 알고리즘은 입력 크기가 커질수록 비효율적입니다. 예를 들어, 배열의 크기가 10,000이라면 대략 100,000,000(1억)의 연산이 필요하게 됩니다.
4단계: 효율적인 접근 방법
효율적인 방법으로 HashMap
을 사용할 수 있습니다. 이 방식은 시간 복잡도를 O(n)으로 줄일 수 있습니다. HashMap
을 사용하면 이전에 본 숫자를 빠르게 검사할 수 있습니다.
public int[] twoSum(int[] nums, int target) { Mapmap = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] {map.get(complement), i}; } map.put(nums[i], i); } throw new IllegalArgumentException("No two sum solution"); }
5단계: 새로운 알고리즘의 시간 복잡도 분석
이 방법의 시간 복잡도는 O(n)입니다. 배열을 한 번만 순회하므로, 중복된 연산이 없습니다. 즉, 배열의 모든 요소를 한 번만 탐색하여 필요한 값을 즉시 찾을 수 있습니다. 이와 같은 개선된 방법은 성능을 크게 향상시킬 수 있습니다.
시간 복잡도 표기법
기본적으로 알고리즘의 성능을 이해하기 위해서는 다음의 시간 복잡도 표기법을 사용합니다:
- O(1) : 상수 시간 복잡도
- O(log n) : 로그 시간 복잡도, 주로 이진 검색에서 사용
- O(n) : 선형 시간 복잡도
- O(n log n) : 선형 로그 시간 복잡도, 주로 정렬 알고리즘에서 볼 수 있음
- O(n2) : 이차 시간 복잡도, 중첩 루프에서 발생
- O(2n) : 지수 시간 복잡도, 피보나치 수 계산 등에 사용
결론
이 글에서는 간단한 알고리즘 문제를 통해 시간 복잡도 표기법에 대해 살펴보았습니다. 알고리즘의 성능을 평가하는 것은 프로그래밍에서 매우 중요한 부분입니다. 주어진 문제의 한계와 최적의 해결 방법을 찾는 능력을 키운다면 코딩 테스트에서 좋은 결과를 얻을 수 있을 것입니다. 다음 단계에서는 더 복잡한 알고리즘과 자료 구조에 대해 다루면서, 성능을 극대화하는 방법을 탐구할 것입니다.
이 기사가 도움이 되셨기를 바랍니다. 자바 코딩 테스트와 시간 복잡도에 대한 더욱 풍부한 내용들이 궁금하시다면 앞으로도 계속 지켜봐 주세요!