연속 부분 수열 합의 개수
문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/131701
접근 방식
조합을 이용해서 풀 수 있는 문제다.
일반적으로 조합의 개수가 주어지고, 조합의 수를 구하는 반면
이 문제는, elements의 길이만큼의 조합의 수를 통해 해결해야 한다.
결과
소스 코드
import java.util.*;
class Solution {
static Set<Integer> set = new HashSet<>();
static int count = 0;
public int solution(int[] elements) {
for(int i=1; i<=elements.length; i++){
for(int j=0; j<elements.length; j++){
comp(0, 0, i, elements, j);
}
}
return set.size();
}
void comp(int sum, int cnt, int target, int[] elements, int start){
if(cnt==target){
set.add(sum);
return;
}
int idx = (start+1) % elements.length;
comp(sum+elements[idx], cnt+1, target, elements, idx);
}
}
조합의 일반적인 풀이 방법인 재귀를 통해 문제를 해결했다.
다만 elements의 길이가 최대 1000까지 주어지다보니, 실행시간이 최대 약 6초까지 나오기도 했다.
다른 접근 방식
dp를 이용한 풀이가 있었다.
처음 원소를 시작으로 하나씩 더 해가면서 조합을 통해 발생한 합을 set 자료구조에 더해가는 방식이다.
이런 방식을 사용할 경우, 시간 복잡도는 최대 O(n^2)로, 100만정도가 나오기 때문에
내 방식보다는 훨씬 빠르고 좋은 방식이다.
프로그래머스 실행 결과 기준, 최대 속도가 약 40배 차이났다.
import java.util.*;
class Solution {
static Set<Integer> set = new HashSet<>();
public int solution(int[] elements) {
int dp[] = new int[elements.length];
for(int i=1; i<=elements.length; i++){
for(int j=0; j<elements.length; j++){
dp[j]+=elements[(i+j-1) % elements.length];
set.add(dp[j]);
}
}
return set.size();
}
}
알게 된 점
조합을 통해 모든 조합을 직접 반복 계산하여 구할 수 있겠지만,
조합의 특성상 한 번만 계산이 되었다면, 이후에는 중복으로 할 필요가 없는 것을 이용해서
이전 조합의 합을 따로 저장해두었다가 필요할 때 사용하여 자원을 절약할 수 있다.
dp적 사고 up