https://school.programmers.co.kr/learn/courses/30/lessons/43165
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
문제 설명
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 함수를 작성해주세요.
입출력 예
numbers target return
[1, 1, 1, 1, 1] 3 5
[4, 1, 2, 1] 4 2
어렵지 않게 풀수 있었는데 numbers가 1이 25개쯤 있으면 코랩에서 11초 걸렸다
def solution(numbers, target):
answer = 0
def dfs(idx, result):
if idx == len(numbers) and result == target:
nonlocal answer
answer += 1
return
if idx == len(numbers):
return
else:
dfs(idx+1, result+numbers[idx])
dfs(idx+1, result-numbers[idx])
result = 0
dfs(0, result)
return answer
numbers = [1 for i in range(25)]
target = 3
solution(numbers, target)
위 동일한 (idx, result) 상태가 여러 경로를 통해 반복될 수 있기 때문에. 이런 중복 계산을 피하면 효율이 향상됩니다.
메모이제이션 기법을 사용하면 501개의 조합도 순식간에 풀었다.
def solution(numbers, target):
memo = {}
def dfs(idx, result):
if (idx, result) in memo:
return memo[(idx, result)]
if idx == len(numbers):
return 1 if result == target else 0
# 현재 상태에서 가능한 경우의 수 계산
plus = dfs(idx + 1, result + numbers[idx])
minus = dfs(idx + 1, result - numbers[idx])
memo[(idx, result)] = plus + minus
return memo[(idx, result)]
return dfs(0, 0)
numbers = [1 for i in range(501)]
target = 3
solution(numbers, target)
위 코드를 보면 plus, minus변수를 더한걸 메모이제이션 하고 있다.
현 분기에서 +,-연산의 경우의 수가 있기 때문에 현분기에서 만들수있는 경우의 수는 +,-를 순회한 경우의 수를 더하면 된다.
**(idx, result)**라는 상태에서 만들 수 있는 모든 경우의 수의 합이기 때문입니다.
🔍 자세히 설명하면:
- dfs(idx, result)는 idx번째 숫자부터 시작해서, 현재까지의 합이 result일 때,
남은 숫자들로 target을 만들 수 있는 경우의 수를 반환합니다. - 여기서 두 가지 선택을 하죠:
- +numbers[idx] → 다음 상태: (idx+1, result + numbers[idx])
- -numbers[idx] → 다음 상태: (idx+1, result - numbers[idx])
- 따라서 이 상태에서 가능한 총 경우의 수는
plus = dfs(idx+1, result + numbers[idx])
minus = dfs(idx+1, result - numbers[idx])
→ 이 둘의 합: plus + minus
📦 그래서 memo[(idx, result)]에 저장하는 이유는:
나중에 같은 상태 (idx, result)가 다시 등장할 때,
이미 계산한 값을 재사용해서 중복 호출을 피하기 위해서입니다.
메모이제이션은 **값 자체(여기선 경우의 수)**를 저장해야 의미가 있습니다.
'코딩테스트' 카테고리의 다른 글
| 프로그래머스 (DFS/BFS)게임 맵 최단거리 (0) | 2025.06.07 |
|---|---|
| 네트워크 - 깊이/너비 우선 탐색(DFS/BFS) - 프로그래머 (0) | 2025.06.05 |
| 백준 1103번 게임 (0) | 2025.06.01 |
| 2025 프로그래머스 코드챌린지 2차 예선완전범죄 (1) | 2025.05.31 |
| 2022 KAKAO BLIND RECRUITMENT신고 결과 받기 (0) | 2025.05.31 |