프로그래머스: 타겟 넘버

승헌·2022년 3월 7일
0

(문제링크)

문제

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]35
[4, 1, 2, 1]42

입출력 예 설명

입출력 예 #1
문제 예시와 같습니다.

입출력 예 #2

+4+1-2+1 = 4
+4-1+2-1 = 4

총 2가지 방법이 있으므로, 2를 return 합니다.

풀이

  1. 가능한 모든 방법을 찾는다.
  2. 타겟 넘버를 만들 수 있는 방법만 카운트한다.

A, B, C, D 네 개로 가능한 모든 경우의 수는 다음과 같다.

ABCD
+A+B+C+D+D
+A+B+C-D-D
+A+B-C+D-C+D
+A+B-C-D-C-D
+A-B+C+D-B+C+D
+A-B+C-D-B+C-D
+A-B-C+D-B-C+D
+A-B-C-D-B-C-D
-A+B+C+D-A+B+C+D
-A+B+C-D-A+B+C-D
-A+B-C+D-A+B-C+D
-A+B-C-D-A+B-C-D
-A-B+C+D-A-B+C+D
-A-B+C-D-A-B+C-D
-A-B-C+D-A-B-C+D
-A-B-C-D-A-B-C-D
  1. 처음에 배열 [+D, -D]이 있다.
  2. 배열에 +C 를 더한 plus 배열과 -C를 더한 minus 배열 두개를 만들어 합친다.
    그럼 [+C+D, +C-D, -C+D, -C-D]가 된다.
  3. 같은 방법으로 B를 더한 배열과 뺀 배열을 만들어 합친다.
    그럼 [+B+C+D, +B+C-D, +B-C+D, +B-C-D, -B+C+D, -B+C-D, -B-C+D, -B-C-D]가 된다.
  4. 같은 방법으로 A도 한다.
    그럼 [+A+B+C+D, +A+B+C-D, +A+B-C+D, +A+B-C-D, +A-B+C+D, +A-B+C-D, +A-B-C+D, +A-B-C-D, -A+B+C+D, -A+B+C-D, -A+B-C+D, -A+B-C-D, -A-B+C+D, -A-B+C-D, -A-B-C+D, -A-B-C-D]

이런 식으로 모든 경우의 수를 구한 뒤, 배열 요소와 타겟 넘버가 일치하는 경우만 카운트했다.

소스코드

function solution(numbers, target) {
    // 가능한 모든 경우의 수 구하기
    let possible = [numbers[0], -numbers[0]];
    for (let i=1; i<numbers.length; i++) {
        let plus = possible.map(x => x+numbers[i]);
        let minus = possible.map(x => x-numbers[i]);
        possible = [...plus, ...minus];
    }
    
    // target과 일치하다면 count++
    let count = 0;
    for (let i=0; i<possible.length; i++) {
        if (possible[i] === target) count++;
    }
    return count;
}

0개의 댓글