PS/Algorithm

투포인터 알고리즘 (Two pointers Algorithm)

포뇨링 2023. 1. 9. 19:44

투포인터 알고리즘은 슬라이딩 윈도우 알고리즘이라고도 하며, 1차원 배열에서 두 개의 포인터를 조작해서 원하는 결과를 얻는 알고리즘이라고 한다.

보통 완전탐색으로 풀어서 시간초과가 날때의 해결책이 될 수 있다고 한다.

 

 


아래 문제가 전형적인 투포인터 알고리즘 문제이다.

https://www.acmicpc.net/problem/2003

 

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차원 배열 중에 합이 M이 되는 부분의 수를 구하는 문제이다.

1) 포인터를 start, end로 지정하고

2) arr[start]부터 arr[end]까지의 합이 M보다 작으면 end포인터를 1 중가시키고

3) M보다 크면 start를 1 증가시키고

4) 같으면 cnt를 1 증가시키고 end를 1 증가시킨다.

5) end가 배열의 끝에 도달하면 종료한다.

 

이 문제를 완전탐색으로 풀면 이중 for문이 필요하기에 시간복잡도는 O(N^2)가 된다. 하지만 투포인터를 이용하면 O(N)이다.

 

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
ll n, m, arr[10010];
ll st, ed, cnt, tmp;

ll arr_sum(ll st, ll ed) {
	ll sum = 0;
	for (ll i = st; i <= ed; i++) {
		sum += arr[i];
	}

	return sum;
}

int main(void) {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> n >> m;

	for (ll i = 0; i < n; i++) {
		cin >> arr[i];
	}

	while (ed != n) {
		tmp = arr_sum(st, ed);
		if (tmp < m) ed++;
		else if (tmp > m) st++;
		else {
			ed++;
			cnt++;
		}
	}

	cout << cnt;
}