[프로그래머스] N으로 표현 풀이 (DP)

2025. 4. 26. 17:05·Algorithm

문제 소개

오늘 풀었던 프로그래머스 - N으로 표현 문제를 정리합니다.

이 문제는 숫자 N을 사칙연산과 이어붙이기만으로 target number를 만드는 문제입니다.

문제의 핵심은 "N을 최대 8번까지 사용해서 최소한의 사용으로 target을 만들 수 있는지"를 찾는 데 있습니다.

문제 링크: N으로 표현 - 프로그래머스


문제 접근 방식

이 문제는 다음과 같은 방식으로 접근했습니다:

  1. DP(동적 프로그래밍) 을 이용해 점진적으로 가능한 숫자들을 만들었습니다. 
    • dp[i] : 숫자i번 쓰고 만들 수 있는 수 모음
  2. 이어붙이는 숫자(예: 5, 55, 555)도 고려해야 했습니다.
  3. 사칙연산(+, -, *, /)을 통해 조합할 수 있는 모든 경우를 생성했습니다.
  4. 숫자 사용 횟수를 1개부터 8개까지 늘려가면서 원하는 수가 만들어지는지 확인했습니다.

 


해결 과정 및 코드

핵심 아이디어

  1. dp[i] = N을 i번 사용해서 만들 수 있는 모든 수들의 집합으로 정의합니다.
  2. dp[1] = {N}, dp[2] = {NN, N+N, N-N, N*N, N/N} 이런 식으로 채워갑니다.
  3. 수식을 만들 때, (앞에 만든 숫자 집합) + (뒤에 만든 숫자 집합) 조합도 모두 고려합니다.
  4. N을 이어붙인 수 (5, 55, 555 같은 것)도 추가해줘야 합니다.
  5. N을 8번까지 사용했는데도 원하는 수를 만들지 못하면 -1을 반환합니다.

코드

시간 복잡도 : 최악의 경우 O(8^2 * M^2)에 가까울 수 있습니다. (M = 각 단계에서 만들 수 있는 숫자의 개수)

import java.util.*;

public class Solution {
    public int solution(int N, int number) {
        if (N == number) return 1;
        
        List<Set<Integer>> dp = new ArrayList<>();
        // 8번 사용하는 경우만 저장할거임
        for (int i = 0; i <= 8; i++) {
            dp.add(new HashSet<>());
        }
        
        dp.get(1).add(N);
        
        for (int i = 2; i <= 8; i++) {
            Set<Integer> current = dp.get(i);
            
            // 이어붙이기: 예를 들면 5, 55, 555
            int concatNumber = Integer.parseInt(String.valueOf(N).repeat(i));
            current.add(concatNumber);
            
            // 이전에 만든 경우를 합친 경우 고려
            for (int j = 1; j < i; j++) { // dp[3] = (dp[1]과 dp[2] 조합, dp[2]와 dp[1] 조합)
                Set<Integer> set1 = dp.get(j);
                Set<Integer> set2 = dp.get(i - j);
                
                for (int a : set1) {
                    for (int b : set2) {
                        current.add(a + b);
                        current.add(a - b);
                        current.add(a * b);
                        if (b != 0) current.add(a / b);
                    }
                }
            }
            
            if (current.contains(number)) {
                return i;
            }
        }
        
        return -1;
    }
}

 


추가: 값 복사 vs 참조 복사 (중요 개념)

이 문제를 풀 때, Set<Integer> current = dp.get(i); 와 같은 코드가 나옵니다.
이 부분에서 "값 복사인가? 참조 복사인가?" 헷갈릴 수 있는데, 정리하면 다음과 같습니다.

복사 방법설명특징
Set<Integer> current = dp.get(i); 참조 복사 current와 dp.get(i) 둘 다 같은 객체를 가리킴
new HashSet<>(dp.get(i)) 값 복사 완전히 독립적인 새 Set 생성
Set<Integer> copy =
(Set<Integer>) ((HashSet<Integer>) original).clone();
값 복사 clone은 별도 객체를 리턴, 형변환 필요
  • current.add(x)를 하면 **dp.get(i)**에도 영향이 가는 이유는 참조 복사이기 때문입니다.
  • 복사본을 따로 만들고 싶으면 new HashSet<>(원본)이나 clone()을 사용해야 합니다.

보통은 new HashSet<>(원본) 방식을 더 선호합니다. (형변환이 필요 없고 가독성이 좋기 때문)

 

'Algorithm' 카테고리의 다른 글

[프로그래머스] 가장 큰 수 풀이 (정렬)  (0) 2025.04.26
[프로그래머스] K번째 수 풀이 (정렬)  (0) 2025.04.26
[프로그래머스] 완주하지 못한 선수 풀이 (Hash)  (0) 2025.04.26
[프로그래머스] 타겟넘버 문제 풀이 (BFS)  (0) 2025.03.17
[백준] 15684 - 사다리 조작 문제 풀이 (백트래킹)  (0) 2025.03.14
'Algorithm' 카테고리의 다른 글
  • [프로그래머스] K번째 수 풀이 (정렬)
  • [프로그래머스] 완주하지 못한 선수 풀이 (Hash)
  • [프로그래머스] 타겟넘버 문제 풀이 (BFS)
  • [백준] 15684 - 사다리 조작 문제 풀이 (백트래킹)
Celion
Celion
오늘도 평소처럼 화이팅!
  • Celion
    Orion Log
    Celion
  • 전체
    오늘
    어제
    • 전체 글 (144)
      • Uncompiled Thoughts (8)
        • 네이버 부스트캠프 10기 (5)
      • CS 기초부터 한 걸음씩 (34)
      • Code Odyssey (22)
      • Algorithm (77)
        • Coding Test Records (63)
      • Git (3)
      • reference (0)
  • 블로그 메뉴

    • 태그
    • 방명록
  • 태그

    java
    greedy
    코테
    문법정리
    Level2
    백준
    Level3
    boostcamp
    알고리즘고득점kit
    프로그래머스
    시뮬레이션
    Kotlin
  • 최근 글

  • 인기 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.4
Celion
[프로그래머스] N으로 표현 풀이 (DP)
상단으로

티스토리툴바