정수 배열 N이 주어졌을 때 두 원소의 합이 특정한 값(T)이 되는 것을 찾는 방법에 대해 생각해보자. 예를 들면, N={-3, -5, 2, -2, 1}이고 T=-4라고 하자.
- 모든 경우를 따져보는 방법 - O(N^2)
- 해시 테이블을 사용하여 한 번만 읽으면서 찾는 방법 - O(N) (해시 테이블이 O(1)일 때)
- 배열을 가리키는 2개의 인덱스(혹은 포인터)를 사용하는 방법 - O(N)
이 글에서는 3번에 대해서 생각해보자. 먼저 정렬하면 N={-5, -3, -2, 1, 2}가 된다. 두 개의 인덱스(low, high)를 사용한다. low는 첫 번째 원소, high는 마지막 원소를 가리키는 인덱스를 저장한다. 각 인덱스가 가리키는 원소의 합(S)을 구해본다. 목푯값인 T와 비교하여 T<S이면 high 값을 감소시킨다. 원소의 합이 목표치보다 크기 때문에 합(S)을 줄여야 하기 때문이다. 마찬가지로, T>S이면 low 값을 증가시킨다. 원소의 합이 목표치보다 작으므로 합(S)을 키워야 하기 때문이다. 이러한 과정을 low<high를 만족하게 하는 동안 수행한다.
위의 예로 값을 구하는 과정을 살펴보면 아래와 같다.
N[low] N[high] S-----------------------------------5 2 -3 (T<S, high--)-5 1 -4 (T=S)
조금 더 문제를 확장해서 두 원소의 합이 T에 가장 가까운 경우를 찾는다고 해보자. 이 경우에도 비슷한 방식으로 하는데, S와 T의 차의 절댓값이 최소가 되는 정보를 유지해야 한다. 절댓값이라는 개념이 들어가는데도 위와 같은 식으로 하는 게 처음에는 잘 이해가 안 되는데 결국 S가 T에 가까워지는 방향으로 가려면 T>S일 떄는 low++, T<S일 때는 high--을 해야 한다.
'[아는게 힘이다] > [프로그래밍]' 카테고리의 다른 글
연결 리스트(Linked List) 부분 뒤집기(reverse) (0) | 2016.03.14 |
---|---|
그래프 색칠하기 (0) | 2016.02.15 |
[C] 몇 가지 코딩 실수 (2) | 2012.05.14 |
[C++/ACM] 820 Internet Bandwidth (0) | 2010.05.16 |