투 포인터

정렬된 배열(또는 리스트)에서 두 개의 인덱스를 양 끝 또는 한쪽 끝에서 시작해 조건에 따라 이동시키며 선형 시간에 답을 찾는 기법입니다.

동작 과정

문제: 정렬된 배열에서 합이 target인 두 수 찾기

A = [1, 3, 5, 7, 9, 11]   target = 14

left=0, right=5  (A[0]=1, A[5]=11)  sum=12 < 14  → left++
left=1, right=5  (A[1]=3, A[5]=11)  sum=14 = 14  → 발견! (3, 11)
sum이 target보다 작다  → left를 오른쪽으로 옮겨 sum을 키운다
sum이 target보다 크다  → right를 왼쪽으로 옮겨 sum을 줄인다
sum이 target과 같다   → 정답, 필요하면 left++, right-- 로 다음 쌍도 탐색

배열이 정렬되어 있기 때문에 left를 옮기면 sum이 커지고 right를 옮기면 sum이 작아진다는 단조성이 보장되어, 모든 (left, right) 쌍을 확인하는 O(N²) 대신 각 인덱스를 한 번씩만 이동해 O(N)에 끝낼 수 있습니다.

구현

int[] twoSumSorted(int[] a, int target) {
    int left = 0, right = a.length - 1;

    while (left < right) {
        int sum = a[left] + a[right];
        if (sum == target) {
            return new int[] { left, right };
        } else if (sum < target) {
            left++;
        } else {
            right--;
        }
    }
    return new int[] { -1, -1 };
}
// 응용: 세 수의 합이 target인 조합 찾기 (하나를 고정하고 나머지에 투 포인터)
boolean threeSumSorted(int[] a, int target) {
    for (int i = 0; i < a.length - 2; i++) {
        int left = i + 1, right = a.length - 1;
        while (left < right) {
            int sum = a[i] + a[left] + a[right];
            if (sum == target) return true;
            else if (sum < target) left++;
            else right--;
        }
    }
    return false;
}

복잡도

구분복잡도근거
시간O(N)두 포인터가 각각 최대 N번만 이동
공간O(1)인덱스 두 개만 사용

입력이 정렬되어 있지 않다면 정렬에 O(N log N)이 먼저 필요합니다. 세 수의 합처럼 하나를 고정하고 나머지에 투 포인터를 적용하는 패턴은 전체 시간복잡도가 O(N²)이 됩니다.

주의사항

핵심 정리

CSLOG에서 보기