Coding Test Practice
DP를 이용한 경우의 수 찾기
마손리
2023. 3. 22. 23:42
문제
여러가지 지폐의 종류로 원하는 액수를 가저갈수 있는 모든 경우의 수를 구하라.
예를들어 $50, $20, $10 3가지의 지폐종류가 있고 총 50 달러를 가저가려할때 가질수 있는 모든 경우의 수인 4를 구해 반환해야 한다.
- $50 * 1
- $20 * 2, $10 * 1
- $20 * 1, $10 * 3
- $10 * 5
입력
int 타입의 자연수 int target
int 타입의 요소를 갖는 배열 int[] type
출력
long 타입의 모든 경우의 수
풀이
재귀
class Solution {
public long ocean(int target, int[] type) {
int[] newType = IntStream.of(type).boxed().sorted(Collections.reverseOrder()).mapToInt(a->a).toArray();
return recursion(newType,target,0);
}
long recursion(int[] newType, int target, long count){
if(target==0) return ++count;
if(newType.length==0) return count;
if(newType[newType.length-1]>target) return count;
int numberOfCoins = target/newType[0];
while(numberOfCoins>=0){
int leftTarget = target - newType[0] * numberOfCoins;
count = recursion(Arrays.copyOfRange(newType,1,newType.length), leftTarget, count);
numberOfCoins--;
}
return count;
}
}
처음 문제를 풀때 재귀를 활용하여 문제를 풀었는데 계속해서 시간초과로 인해 실패하였다... 이후 동적계획법에 대해 알게되어 이것을 이용하였더니 오류없이 통과할 수 있었다.
DP - Bottom up
class Solution {
public long ocean(int target, int[] type) {
long[] table = new long[target + 1];
table[0] = 1;
for(int i = 0; i < type.length; i++) {
for(int j = 1; j <= target; j++)
if(type[i] <= j)
table[j] += table[j-type[i]];
}
return table[target];
}
}
동적계획법 중 Bottom_up을 이용하였으며 그에 관한 포스트는 아래 링크에...
https://mason-lee.tistory.com/79
마무리 (수도 코드 작성 팁)
여지껏 수도코드를 작성안하고 코딩테스트를 풀어 왔었는데 막상 수도코드를 작성하려고 하니 막막했다.
심지어 수도코드를 작성하고 코드의 풀이가 더 뒤죽박죽되며 복잡해지고 결과가 원하는대로 나오지 않는 등 많은 문제가 생기게 되어 수도 코드 작성시 몇가지 룰을 정하게 되었다.
- 모든 테스트 코드의 경우의 수를 담는 입력값을 만들고 (혹은 그런 테스트 코드를 사용) 그에 맞는 결과값을 일단 도출
- 입력값과 출력값의 상관관계 혹은 해당 출력값이 나오게된 원리, 구조, 법칙등을 파악하고 어떠한 순서와 규칙이 숨어 있는지 파악
- 파악한 규칙을 토대로 수도코드를 작성