| 항목 | 2003번: 수들의 합 2 | 2559번: 수열 | 3273번: 두 수의 합 |
|---|---|---|---|
| 문제 핵심 | 연속된 부분합 중 M과 같은 구간 개수 | 길이 K인 연속 구간 합 최대값 | 서로 다른 두 수 합이 X인 경우 개수 |
| 배열 조건 | N개의 정수 | N개의 정수 | N개의 정수 (임의 순서) |
| 연속성 | ✅ 연속 구간 | ✅ 연속 구간 | ❌ 임의 두 수 |
| 주요 알고리즘 | 투포인터(슬라이딩 윈도우) | 투포인터(슬라이딩 윈도우) | 투포인터(정렬 후 양 끝) / 이중 for문 가능 |
| 투포인터 포인터 이동 | sum >= M → left++ sum < M → right++ | 길이 K 초기 합 → left++/right++ 슬라이딩 | sum < X → left++ sum > X → right-- sum == X → count++ + 한쪽 이동 |
| sum 처리 방식 | 누적합(sum += arr[right], sum -= arr[left]) 가능 | 누적합(sliding sum) 가능 | 누적 X, 항상 sum = arr[left] + arr[right] 새로 계산 |
| 시간복잡도 | O(N) | O(N) | O(N) (투포인터) / O(N²) (이중for문) |
| 핵심 포인트 | 연속 구간 → 누적합 활용 | 길이 고정 → 누적합 활용 | 임의 두 수 → sum 누적 X, 포인터 이동 조심 |
2003 (연속 구간, 투포인터)
package A0study;
import java.io.*;
import java.util.*;
public class p2003_수들의합2 {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int[] arr = new int[N];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
int left = 0; // 시작 포인터
int right = 0; // 끝 포인터
int sum = 0; // 현재 부분합
int count = 0; // 정답 개수
// 방법 1
while(true) {
if(sum >= M) {
sum -= arr[left];
left++;
} else if (right == N) {
break;
} else {
sum += arr[right];
right++;
}
if(sum == M) {
count++;
}
}
// 방법 2
while (right < N) {
sum += arr[right]; // right를 하나씩 늘리면서 합 누적
right++;
while (sum > M) { // sum이 M보다 크면 left를 늘려서 줄임
sum -= arr[left];
left++;
}
if (sum == M) { // sum이 딱 맞으면 count++
count++;
}
}
System.out.println(count);
}
}
2559 (연속 구간, 투포인터)
package A0study;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class p2559_수열 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int K = Integer.parseInt(st.nextToken());
int[] arr = new int[N];
st = new StringTokenizer(br.readLine());
for(int i=0; i<N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
int sum = 0;
for(int i=0; i<K; i++) {
sum += arr[i];
}
int max = sum;
for(int i=K; i<N; i++) {
sum = sum - arr[i-K] + arr[i];
if(sum > max) {
max = sum;
}
}
System.out.println(max);
}
}
3273 (임의 두 수, 정렬 + 양 끝 투포인터)
package A0study;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class p3273_두수의합 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
int[] arr = new int[N];
for(int i=0; i<N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
int X = Integer.parseInt(br.readLine());
// 1. 정렬
Arrays.sort(arr);
// 2. 투포인터
int left = 0;
int right = N-1;
int cnt = 0;
while(left < right) {
int sum = arr[left] + arr[right];
if (sum == X) {
cnt++;
right--;
} else if (sum < X){
left++;
} else {
right--;
}
}
System.out.println(cnt);
}
}