1. 문제를 이해한다
- 괄호와 사칙 연산을 이용하여 number를 n으로 표현한다. 그 중 n이 사용된 횟수가 가장 적은 경우의 횟수를 결과값으로 돌려준다.
- n : 1 ~ 9 사이의 정수 n이 주어진다. 
- number : 32000이하의 정수가 주어진다. 

2. 문제를 재정의한다.
- number(k) = (n이 k번 사용되어 나온 결과 값) = number(j) [+, -, *, /] number(k-j) (단,  j 는 1보다 크고 k보다 작다.  k-j는 0이 아니다.)

3. 문제 풀이를 계획한다
1) number(1)의 집합을 구한다 : {n} (주어진 n 1개로 이루어진 집합)
2) number(2)의 집합을 구한다 : {n} [+, -, *, /] {n}
...
n) number(k)의 집합을 구한다.
* number(k)의 집합은 Set으로 구현하여 중복을 제거한다.
* number(k)의 집합을 구하는 과정에서 주어진 number와 값이 같은 경우가 있을 경우 k값 반환 

4. 문제 풀이를 검증한다.

5. 구현한다.

public static int solution(int N, int number) {
		/*
		 *  8개의 HashSet을 만든다. (0번째 HashSet은 사용하지 않음) 
		 */
		HashSet[] sets = new HashSet[9];
		for(int i=0; i<sets.length; i++) {
			sets[i] = new HashSet<Integer>();
		}
		/*
		 *  5, 55, 555, 5555 와 같은 값들은 연산의 결과 값이 아니므로
		 *  연산 이전에 미리 Set에 포함시킨다.
		 */
		for(int i=1; i<sets.length; i++) {
			String enumerate = "";
			for(int j=0; j<i; j++) {
				enumerate += N;
			}
			sets[i].add(new Integer(enumerate));
		}
		
		/*
		 * i 번째 set을 구한다.
		 * j번째 set과 (i-j)번째set을 사칙연산하여 결과 값을 i번째 set에 더한다. 
		 */
		for(int i=1; i<sets.length; i++) {
			for(int j=1; j<i; j++) {
				HashSet<Integer> preSet = sets[j];
				HashSet<Integer> postSet = sets[i-j];
				for(int k : preSet) {
					for(int l : postSet) {
						sets[i].add(k + l);
						sets[i].add(k * l);
						sets[i].add(Math.abs(k - l));
						if(l != 0) sets[i].add(k / l);
					}
				}
			}
			System.out.println(i + "set !!");
			System.out.println(sets[i]);
			if(sets[i].contains(number)) return i;
		}
		/*
		 * 8번째 set안에 포함되지 않았다는 것은 n이 9번 이상 필요하다는 것이므로
		 * -1을 반환한다. 
		 */
        int answer = -1;
        return answer;
    }

6. 회고한다.
 풀이 방법을 몰랐을 때는 엄한 방식으로 삽질하면서 "내가 풀 수 있는 수준인가" 싶었는데, 방법을 알고 한 단계 한 단계 풀어보니 생각보다 간단하다..

 

'알고리즘 > 문제풀이' 카테고리의 다른 글

[프로그래머스] 타겟넘버(DFS)  (0) 2020.02.02

+ Recent posts