투포인터는 전혀 알지 못했는데 카카오 코딩테스트 문제를 풀다가 우연히 알게 되었습니다. 처음 봤을 때 2개의 변수값을 조금씩 움직여가는것이 매개변수 탐색과 비슷하다고 생각했습니다.
투포인터는 1차원 배열에서 각각의 index를 가리키는 2개의 변수를 조작해가면서 문제를 해결하는 기법입니다. 투포인터를 백준문제를 보면서 설명하겠습니다.
2003번: 수들의 합 2
첫째 줄에 N(1≤N≤10,000), M(1≤M≤300,000,000)이 주어진다. 다음 줄에는 A[1], A[2], …, A[N]이 공백으로 분리되어 주어진다. 각각의 A[x]는 30,000을 넘지 않는 자연수이다.
www.acmicpc.net
문제는 1차원 배열에서 i번째에서 j번째까지의 합이 M이 되는 경우의 수를 구하는 문제입니다. 단순히 2중 for문을 사용하면 쉽게 구할 수 있지만 이 경우 시간복잡도는 O(N^2)입니다. 하지만 투포인터를 사용하면 O(N)만에 답을 구할 수 있습니다 !
먼저 2개의 변수 s,e 0를 초기화 하고 sum 변수를 선언합니다. sum은 s~e까지의 합을 의미합니다.
만약 현재 sum값이 M보다 작으면 e번째 값을 넣고 e++합니다. 그리고 sum값이 M과 같거나 크다면 s값을 빼고 s--합니다. 만약 sum과 M이 같다면 개수를 세어줍니다. 이 과정을 e가 배열을 벗어나지 않을떄까지 반복하는 것입니다.
1. sum < M 이면 sum에 arr[e]를 더하고 e++
2. sum >= 이면 sum에서 arr[s]를 빼고 s++, 만약 sum = M이면 count++
3. 1,2번 과정을 반복하다가 e가 배열의 크기와 같으면 종료한다.
#include <iostream>
using namespace std;
int main()
{
int N, M;
int arr[10001] = {0};
cin >> N >> M;
for (int i = 0; i < N; i++)
{
cin >> arr[i];
}
int s = 0, e = 0;
int sum = 0;
int count = 0;
while (true)
{
if (sum >= M)
{
if (sum == M)
{
count++;
}
sum -= arr[s]; // sum값이 M보다 크거나 같으면 s위치값을 빼주고 s++
s++;
}
else if (e == N) // 끝에 도달하면 break
{
break;
}
else
{
sum += arr[e]; // sum값이 M보다 작으면 계속 e위치 값을 더해준다
e++;
}
}
cout << count << endl;
return 0;
}
'computer science > 알고리즘' 카테고리의 다른 글
[알고리즘] 구간 합(prefix sum) (0) | 2020.09.25 |
---|---|
[알고리즘] 최단거리 알고리즘(Dijkstra,Floyd Warshall) (0) | 2020.09.22 |
[알고리즘] 최소비용 알고리즘(Kruskal's, Prim's) (0) | 2020.09.18 |
[알고리즘] Union-Find 알고리즘 (0) | 2020.09.15 |
[알고리즘] 기수 정렬(Radix Sort) (0) | 2020.05.26 |