https://programmers.co.kr/learn/courses/30/lessons/43165
문제 설명
n개의 음이 아닌 정수가 있습니다. 이 수를 적절히 더하거나 빼서 타겟 넘버를 만들려고 합니다. 예를 들어 [1, 1, 1, 1, 1]로 숫자 3을 만들려면 다음 다섯 방법을 쓸 수 있습니다.
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
사용할 수 있는 숫자가 담긴 배열 numbers, 타겟 넘버 target이 매개변수로 주어질 때 숫자를 적절히 더하고 빼서 타겟 넘버를 만드는 방법의 수를 return 하도록 solution 함수를 작성해주세요.
제한사항
- 주어지는 숫자의 개수는 2개 이상 20개 이하입니다.
- 각 숫자는 1 이상 50 이하인 자연수입니다.
- 타겟 넘버는 1 이상 1000 이하인 자연수입니다.
입출력 예
numberstargetreturn
[1, 1, 1, 1, 1] | 3 | 5 |
입출력 예 설명
문제에 나온 예와 같습니다.
접근 방식
배열의 모든 원소를 다 이용해서 target 값과 일치하는 경우를 찾는 문제
배열의 원소에 하나씩 마이너스를 붙인 뒤 모든 원소의 합을 target과 비교해나가는 방식으로 DFS를 이용해 구현했다.
다음 깊이로 넘어가 탐색이 가능한 경우는 모든 배열의 합이 target보다 큰 경우이다.
배열의 합이 target보다 작은 경우는 무슨 짓을 해도 target에 도달할 수 없다.
예를 들어 배열이 [1, 2, 3, 4, 5]이고 target이 9라고 해보자.
이 때 배열의 합은 1+2+3+4+5=15로 target보다 크다.
첫 번째 원소 1을 -1로 바꾸고 다음 깊이로 넘긴다.
이 때 배열의 합은 -1+2+3+4+5=13으로 target보다 크다.
두 번째 원소 2를 -2로 바꾸고 다음 깊이로 넘긴다.
이 때 배열의 합은 -1-2+3+4+5=9로 target과 일치한다. answer++를 해준 뒤 종료를 한다.
중복을 제거하기 위해 다음 깊이로 넘어가는 경우에는 해당 배열의 이전 원소들은 건들지 않는다.
소스 코드
import java.util.Arrays;
public class Solution {
private int answer = 0;
public int solution(int[] numbers, int target) {
if (Arrays.stream(numbers).sum() < target) {
return 0;
}
for (int i = 0; i < numbers.length; i++) {
numbers[i] = -numbers[i];
dfs(numbers, target, i);
numbers[i] = -numbers[i];
}
return answer;
}
private void dfs(int[] numbers, int target, int index) {
if (Arrays.stream(numbers).sum() == target) {
answer++;
} else if (Arrays.stream(numbers).sum() >= target) {
for (int i = index + 1; i < numbers.length; i++) {
numbers[i] = -numbers[i];
dfs(numbers, target, i);
numbers[i] = -numbers[i];
}
}
}
}
'Tech > Problem Solving' 카테고리의 다른 글
[백준 16236] 아기 상어 (Java) (0) | 2020.04.14 |
---|---|
[프로그래머스 - DFS] 네트워크 (Java) (0) | 2020.04.10 |
[백준 2805] 나무 자르기 (Java) (0) | 2020.04.04 |
[백준 2217] 로프 (Java) (0) | 2020.03.09 |
[백준 11057] 오르막 수 (Java) (0) | 2020.03.07 |