프로그래머스 - 타겟 넘버

Computer Science/Problem Solving

문제 설명

제한사항 및 입출력

풀이

처음 문제를 봤을 때 dp와 dfs가 생각났다. 먼저 dfs 풀이는 각 숫자마다 -, + 두 가지 경우의 수를 모두 탐색하면서 내려가는 경우이다. 내려가면서 남은 모든 수를 더하거나 뺐을 때 목표 숫자가 나오지 않는다면 가지치기해주어서 최적화해줄 수 있다.

내 코드

def solution(numbers, target):
    ans = 0
    
    n = len(numbers)
    # 가지치기를 위한 누적합 배열
    suffix = [0] * (n+1)
    for i in range(n-1, -1, -1):
        suffix[i] = suffix[i+1] + numbers[i]

    def dfs(idx, total):
        nonlocal ans
        
        # 가지치기 조건: 남은 모든 수를 더해도 target 보다 작을 때 혹은 모든 수를 빼도 target 보다 클 때
        if abs(target - total) > suffix[idx]:
            return
        
        # 탈출조건: 배열의 마지막에 도착
        if idx == n:
            if total == target:     # 지금까지 더한 숫자가 target과 같으면 ans += 1
                ans += 1
            return
        
        dfs(idx+1, total + numbers[idx])
        dfs(idx+1, total - numbers[idx])

    dfs(0, 0)
    return ans

 

이렇게 모든 경우의 수를 탐색하면 몇 개가 가능한지 확인할 수 있다.

 

시간 복잡도: 각 원소마다 2가지 부호를 모두 확인하며 진행하므로 O(2^n)이다. n <= 20이므로 최악의 경우에도 약 100만 정도의 크기이기 때문에 무난하게 통과한다. 또한 중간 가지치기로 인해 실제 계산 횟수는 조금? 더 작아질 것이다.

고찰

dp방식의 풀이이다. 가능한 합과 그 개수를 단계별로 누적하여 풀이할 수 있다.

 

dp테이블의 정의는 다음과 같이 내렸다.

dp[i] = i를 만들 수 있는 경우의 수

def solution(numbers, target):
    S = sum(numbers)
    off = S
    
    dp = [0] * (2*S + 1)
    dp[off] = 1
    for i in numbers:
        nxt = [0] * (2*S + 1)
        for s in range(-S, S + 1):
            cnt = dp[s + off]
            if cnt:
                nxt[s + i + off] += cnt
                nxt[s - i + off] += cnt
        dp = nxt
        
    return dp[target + off] if -S <= target <= S else 0

시간 복잡도: O(n * s)이다. s는 모든 수를 더했을 때의 상한으로, 모든 상태공간을 만들어주기 위해 상한값을 구하여 계산해주었다.

 

추가적으로 모든 상태공간을 미리 만들어두지 않고 dictionary를 사용하여 모든 상태공간을 만들지 않고도 풀이할 수 있다.

from collections import Counter

def solution(numbers, target):
    # i: j -> i = 만들 수 있는 값, j = 방법의 수
    dp = Counter({0: 1})
    
    for i in numbers:
        nxt = Counter()
        
        for s, c in dp.items():
            nxt[s+i] += c
            nxt[s-i] += c
        dp = nxt
        
    return dp[target]

 

'Computer Science > Problem Solving' 카테고리의 다른 글

프로그래머스 - 네트워크  (0) 2025.11.03
프로그래머스 - 멀리 뛰기  (0) 2025.11.03
백준 2539 - 모자이크  (0) 2025.09.28
백준 21278 - 호석이 두 마리 치킨  (0) 2025.09.18
백준 16946 - 벽 부수고 이동하기 4  (0) 2025.09.14
'Computer Science/Problem Solving' 카테고리의 다른 글
  • 프로그래머스 - 네트워크
  • 프로그래머스 - 멀리 뛰기
  • 백준 2539 - 모자이크
  • 백준 21278 - 호석이 두 마리 치킨
hojoo
hojoo
그냥 개발이 즐거운 사람
  • hojoo
    dev_record
    hojoo
  • 전체
    오늘
    어제
    • 분류 전체보기 (82)
      • Study (0)
        • 모든 개발자를 위한 HTTP 웹 기본 지식 (0)
        • Real MySQL 8.0 (0)
        • 친절한 SQL 튜닝 (0)
        • 도메인 주도 개발 시작하기 (0)
        • 대규모 시스템 설계 기초 (0)
      • Computer Science (66)
        • Problem Solving (30)
        • Data Structure (4)
        • Spring Boot (13)
        • DB (1)
        • Java (4)
        • OS (3)
        • Server (2)
        • Tech (0)
      • Security (16)
        • Reversing (15)
        • Assembly (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    n+1
    서버 증설 횟수
    프로그래머스
    n^2 배열 자르기
    Reversing
    21278
    백준
    HTTP
    자료구조
    bean
    dreamhack.io
    레나 튜토리얼
    소수상근수
    9421
    리버싱 핵심원리
    15973
    13265
    Header
    16946
    2539
    DP
    19622
    12033
    리버싱
    Spring boot
    Lena tutorial
    DB
    x64dbg
    PE header
    servlet
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
hojoo
프로그래머스 - 타겟 넘버
상단으로

티스토리툴바