Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 | 31 |
Tags
- 2167
- 백준 1806
- 백준 2635
- boj 1503
- boj 2636
- boj 2167
- boj 2470
- 백준 2661
- 백준 2470
- 10800
- boj 1697
- boj 2667
- 백준 19238
- boj 2178
- 백준 1697
- boj 10800
- 백준 2167
- boj 1806
- boj 19238
- boj 2108
- boj 2206
- 백준 2108
- 백준 2206
- 백준 2636
- boj 2661
- 백준 10800
- 2636
- 백준 1503
- 백준 2178
- boj 2635
Archives
- Today
- Total
말랑말랑한 개발자 이야기
[백준 2003번] 수들의 합 2 본문
[백준 2003번] 수들의 합 2
문제
N개의 수로 된 수열 A[1], A[2], …, A[N] 이 있다. 이 수열의 i번째 수부터 j번째 수까지의 합 A[i] + A[i+1] + … + A[j-1] + A[j]가 M이 되는 경우의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N(1 ≤ N ≤ 10,000), M(1 ≤ M ≤ 300,000,000)이 주어진다. 다음 줄에는 A[1], A[2], …, A[N]이 공백으로 분리되어 주어진다. 각각의 A[x]는 30,000을 넘지 않는 자연수이다.
출력
첫째 줄에 경우의 수를 출력한다.
풀이
#include <iostream>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N,M;
cin >> N >> M;
vector<int> temp;
for(int i=0;i<N;i++){
int a;
cin >> a;
temp.push_back(a);
}
int left=0, right=0;
int cnt = 0;
int sum = 0;
while(right <= N){
if(sum < M){
sum += temp[right++];
}
else if(sum > M){
sum -= temp[left++];
}
else{
cnt++;
sum += temp[right++];
}
}
cout << cnt;
return 0;
}
처음에는 1644번을 풀어보려고 하다가 투 포인터에 대한 개념을 알고자 이 문제를 풀어보았다. 투포인터를 모른다면 아마 나처럼 구간 합을 응용해서 풀고자 할 것이다. 하지만 O(1)로 구간 합을 구하더라고 M이 되는 경우의 수를 구하는 과정에서 O(N^2)의 큰 시간이 소모된다. 따라서 구간 합으로 푸는 것은 적절하지 않고 투 포인터를 사용해야 한다. 투포인터는 시간 복잡도가 무려 O(1) 밖에 되지 않는다.
투 포인터는 배열에서 다른 원소를 가리키는 2개의 포인터를 이용하여 원하는 값을 계산하는 방식으로 left, right 두개의 포인터로 문제를 풀었다. 투 포인터에 대한 자세한 설명은 m.blog.naver.com/kks227/220795165570 에 있다.
'알고리즘 > 백준' 카테고리의 다른 글
[백준 4358번] 생태학 (0) | 2021.01.10 |
---|---|
[백준 14425번] 문자열 집합 (0) | 2021.01.10 |
[백준 1339번] 단어 수학 (0) | 2021.01.09 |
[백준 11659번] 구간 합 구하기 4 (0) | 2021.01.09 |
[백준 1929번] 소수 구하기 (0) | 2021.01.08 |