정의
투포인터란 포인터 2개를 조작하여 원하는 결과를 얻는 방법이다
- 무식하게 for문을 사용하면 O(N^2)이지만 투 포인터는 O(N)
구간 용어 | ||
폐구간 | 이상~이하 | [ ] |
개구간 | 초과~미만 | ( ) |
반개구간 | 초과~이하 | ( ] |
이상~미만 | [ ) |
같은 방향의 투 포인터
- 주로 구간의 경우의 수를 구하는데 사용한다
- 배열의 원소가 모두 자연수여야 한다
- 배열이 정렬 되어 있지 않아도 된다.
알고리즘 원리 | |
초기 상태 | 포인터 2개 모두 출발점 |
종료 조건 | 종료 포인터가 끝에 도달할 때까지 알고리즘 반복 |
동작 | 구간 합이 목표보다 작으면 종료 포인터 전진 구간 합이 목표보다 크거나 같으면 시작 포인터 전진 |
예시코드 (백준 2003번)
int arr[1001];
// 구간합 경우의 수 구하기
int twoPoint(int n, int k) { // 원소 수, 목표
int sum = 0, ret = 0;
int st = 0, en = 0;
while(en < n) {
sum += arr[en++];
while(sum >= k) {
if(sum == k) ans++;
sum -= arr[st++];
}
}
return ret;
}
다른 방향의 투 포인터
- 두 원소의 경우의 수를 구할 때 사용할 수 있다.
- 배열이 1개 또는 2개일 때 사용한다.
- 음수가 있어도 된다.
- 배열의 원소가 정렬 되어 있어야 한다.
알고리즘 원리 | ||
초기 상태 | 시작 포인터는 0, 종료 포인터는 N-1 | |
종료 조건 | 배열 1개 | 시작 포인터가 종료 포인터보다 작을 때까지 반복 |
배열 2개 | 시작 포인터가 도착점보다 작고, 종료 포인터가 출발점보다 같거나 클 때까지 반복 |
|
동작 | 두 원소의 연산이 목표보다 작으면 포인터 전진 도 원소의 연산이 목표보다 크면 포인터 전진 |
예시 코드 (백준 7453번)
// 두 원소의 합 경우의 수 구하기
int A[101], B[101];
int twoPoint(int n, int k) {
int ans = 0;
int st = 0, en = n - 1;
sort(A, A + n);
sort(B, B + n);
// while(st < en) { // 배열 1개
while(st < n && en >= 0) { // 배열 2개
if(A[st] + B[en] == k) {
int ai = 0, bi = 0;
// 중복된 것을 더하기
while(st + ai < n && A[st] == A[st + ai])
ai++;
while(en - bi >= 0 && B[en] == B[en - bi])
bi++;
ans += ai * bi;
st += ai;
en -= bi;
}
else if(A[st] + B[en] > k)
en--;
else
st++;
}
return ans;
}