일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 분할 정복
- BFS
- 크루스칼
- 미래는_현재와_과거로
- c++
- 플로이드 와샬
- object detection
- 자바스크립트
- dropout
- 가끔은 말로
- 조합론
- pytorch
- 알고리즘
- 너비 우선 탐색
- 2023
- 가끔은_말로
- 백트래킹
- 다익스트라
- DP
- 회고록
- dfs
- 세그먼트 트리
- tensorflow
- 이분 탐색
- 우선 순위 큐
- lazy propagation
- 문자열
- NEXT
- Overfitting
- back propagation
- Today
- Total
Doby's Lab
백준 2003번: 수들의 합 2 (C++), 투 포인터 본문
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
종종 유용하게 사용되는 테그닉, 투 포인터(Two Pointers)에 대해 알아보자.
예를 들어, 배열 A가 존재한다고 했을 때, 링크를 걸어둔 문제처럼 A[i] + A[i+1] + … + A[j-1] + A[j] 중 M이 되는 경우의 수를 구하라 했을 때, 어떻게 할 것인가?
구간 합이라 세그먼트 트리를 이용해야 할 거 같지만 세그먼트 트리를 구성한 다음 쿼리는 어떻게 짤 것인지 생각해보면 막막하기만 하다. 이럴 때, 세그먼트 트리를 이용하지도 않고, 투 포인터 알고리즘을 사용하면 된다.
투 포인터는 말 그대로 포인터를 두 개 사용하여 포인터가 가리키는 시작점과 끝점에서 일어나는 일, 혹은 시작점과 끝 점 사이에서 일어나는 일을 처리하기에 편한 알고리즘이다.
Time Complexity는 right가 누적으로 N번까지 가야 끝이 나기 때문에 O(N)이다. left가 right와 같이 끝까지 가더라도 빅오 표기법에 의해 시간 복잡도는 O(N)이 된다.
두 포인터를 가리키는 말은 [start, end], [left, right]처럼 본인이 편한 대로 사용하는 것이 좋다.
이 포스팅에서는 left와 right로 하겠다.
[동작 원리]
- left, right 둘 다 똑같은 시작점에서 시작한다.
- 만족하는 m이 되거나 m보다 커지기 전까지 right를 움직인다.
- right를 움직이면서 해당 right 인덱스의 배열의 값들을 더해나간다.
- 만약 right를 움직이는 조건의 반대가 되었다면
- left가 가리키는 인덱스의 배열 값을 빼고, left를 움직이게 한다.
- right가 배열의 크기를 넘어서는 순간, 알고리즘을 종료시킨다.
이렇게 말보다 코드를 보는 것이 더 효율적일 수도 있다.
[AC 코드]
#include <iostream>
#include <vector>
#define left l
#define right r
using namespace std;
vector<long> v;
int n;
long m;
long sum = 0;
int left = 0;
int right = 0;
int answer = 0;
void twoPointers(){
while(true){
if(sum >= m){
sum -= v[left];
left++;
}
else{
if(right == n) break;
sum += v[right];
right++;
}
if(sum == m) answer++;
}
}
int main(){
cin >> n >> m;
for(int i = 0; i < n; i++){
int a; cin >> a;
v.push_back(a);
}
twoPointers();
cout << answer;
return 0;
}
'PS > BOJ' 카테고리의 다른 글
백준 1766번: 문제집 (C++) (0) | 2022.03.14 |
---|---|
백준 1806번: 부분합 (C++) (0) | 2022.03.13 |
백준 1516번: 게임 개발 (C++) (0) | 2022.03.10 |
백준 2252번: 줄 세우기 (C++) (0) | 2022.03.09 |
백준 1005번: ACM Craft (C++) (0) | 2022.03.09 |