코딩테스트
[백준] 1208번 '부분수열의 합 2' - Java
CuckooBird
2023. 8. 22. 19:22
https://www.acmicpc.net/problem/1208
1208번: 부분수열의 합 2
첫째 줄에 정수의 개수를 나타내는 N과 정수 S가 주어진다. (1 ≤ N ≤ 40, |S| ≤ 1,000,000) 둘째 줄에 N개의 정수가 빈 칸을 사이에 두고 주어진다. 주어지는 정수의 절댓값은 100,000을 넘지 않는다.
www.acmicpc.net
문제
코드
import java.io.*;
import java.util.*;
public class Main {
private static final BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
private static final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
private static long[] arr;
private static List<Long> left = new ArrayList<>();
private static List<Long> right = new ArrayList<>();
public static void main(String[] args) throws IOException {
StringTokenizer st = new StringTokenizer(bf.readLine());
int n = Integer.parseInt(st.nextToken());
int s = Integer.parseInt(st.nextToken());
st = new StringTokenizer(bf.readLine());
arr = new long[n];
for(int i = 0 ; i < n ; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
// 입력받은 수열을 반으로 나누고, 반으로 나뉜 수열에서 구할 수 있는 합의 경우를 left, right에 넣음
// -7, -3, -2, 5, 8 을 입력받았을 경우에 -7, -3 / -2, 5, 8 로 나뉘고
// left = [-10, -7, -3, 0] / right = [-2, 0, 3, 5, 6, 8, 13] 으로 들어가게 됨
getSubSequence(0, n / 2, 0, left);
getSubSequence(n / 2, n, 0, right);
Collections.sort(left);
Collections.sort(right);
// left와 right를 더함
long cnt = 0;
int pl = 0, pr = right.size() - 1;
while(pl < left.size() && pr >= 0) {
long sum = left.get(pl) + right.get(pr);
// 합이 s가 나오는 경우에 배열에 같은 수가 있는지 확인하여 그 개수를 곱하여 cnt에 더함
// 만약 [2, 2, 3, 4] 와 [1, 4, 4, 4] 가 있을 경우에, 2는 2개, 4는 3개 이므로 2 * 3을 cnt에 더해줌
if(sum == s) {
long a = left.get(pl);
long cnt1 = 0;
while(pl < left.size() && left.get(pl) == a) {
pl ++;
cnt1 ++;
}
long b = right.get(pr);
long cnt2 = 0;
while(pr >= 0 && right.get(pr) == b) {
pr --;
cnt2 ++;
}
cnt += cnt1 * cnt2;
}
// 더한 값이 s보다 작으면 왼쪽 배열을 움직임
else if(sum < s) pl ++;
// 더한 값이 s보다 크면 오른쪽 배열을 움직임
else pr --;
}
// s == 0 인 경우에는 두 집합의 0 이 더해지는 경우가 포함되기 때문에 1을 빼줌
if(s == 0) cnt --;
bw.write(cnt + "\n");
bf.close();
bw.flush();
bw.close();
}
public static void getSubSequence(int idx, int end, long sum, List<Long> list) {
if(idx == end) {
list.add(sum);
return;
}
getSubSequence(idx + 1, end, sum + arr[idx], list);
getSubSequence(idx + 1, end, sum , list);
}
}
투 포인터를 이용한 코드입니다.