124 나라의 숫자
문제정의
10진법을 1,2,4에 존재하는 나라의 규칙에 따라 새로 나타내는 문제이다. 규칙을 찾아내는 것이 관건인데, 필자는 다른 사람들이랑 다른 관점으로 풀었다(코드 길이는 훨씬 길다).
문제풀이
전체 코드는 다음과 같다. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66public class Country124Num {
//프로그래머스 문제풀이 level2 124 나라의 숫자
public static void main(String[] args)
{
int n = 6;
StringBuilder buff = new StringBuilder();
while(n > 0)
{
int r = n % 3;
n/=3;
buff.append(String.valueOf(r));
}
char[] arr = buff.reverse().toString().toCharArray();
for(int i = arr.length-1; i >= 0; i--)
{
if(arr[i] == '0')
{
int p = i;
for(int j = i; j >=0; j--)
{
if(arr[j] != '0')
{
p = j;
break;
}
}
if(p != i)
{
for(int k = p; k < i; k++)
{
int pre_num = Integer.parseInt(String.valueOf(arr[k]));
char pre_char = Character.forDigit(pre_num-1, 10);
arr[k] = pre_char;
int aft_num = Integer.parseInt(String.valueOf(arr[k+1]));
char aft_char = Character.forDigit(aft_num+3, 10);
arr[k+1] = aft_char;
}
}
}
}
int start_idx = 0;
for(int i = 0; i < arr.length; i++)
{
if(arr[i] != '0')
{
start_idx = i;
break;
}
}
for(int i = start_idx; i < arr.length; i++)
{
if(arr[i] == '3')
arr[i] = '4';
}
String answer = new String(arr);
answer = answer.substring(start_idx, arr.length);
System.out.println(answer);
}
}1
2
3
4
5
6
7while(n > 0)
{
int r = n % 3;
n/=3;
buff.append(String.valueOf(r));
}
char[] arr = buff.reverse().toString().toCharArray();
이해를 돕기 위해 그림을 첨부한다.
초등학생 때 했던 10진수 빼기를 생각하면 된다.
이 부분에서 시간복잡도는 3으로 나눴을 때의 자릿수만큼이므로 \(O(log3(n))\)이다.
말이 길었는데 이것만 이해하면 나머지는 코드만 읽으면 된다. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29for(int i = arr.length-1; i >= 0; i--)
{
if(arr[i] == '0')
{
int p = i;
for(int j = i; j >=0; j--)
{
if(arr[j] != '0')
{
p = j;
break;
}
}
if(p != i)
{
for(int k = p; k < i; k++)
{
int pre_num = Integer.parseInt(String.valueOf(arr[k]));
char pre_char = Character.forDigit(pre_num-1, 10);
arr[k] = pre_char;
int aft_num = Integer.parseInt(String.valueOf(arr[k+1]));
char aft_char = Character.forDigit(aft_num+3, 10);
arr[k+1] = aft_char;
}
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14for(int i = 0; i < arr.length; i++)
{
if(arr[i] != '0')
{
start_idx = i;
break;
}
}
for(int i = start_idx; i < arr.length; i++)
{
if(arr[i] == '3')
arr[i] = '4';
}
따라서 최종 시간복잡도는 \(O(log3(n))\) 이다.
테스트
60줄을 넘었는데 다른 풀이는 고작 10줄안에 끝나서 절망했다. 하지만 할 수 있는건 계속 문제를 풀어나가는 수 밖에 없다. n에 나머지 연산을 해주고 나눌 때 3의 배수이면 -1을 해줬는데, 자릿수를 올리지 않기 위해서 그랬다고 하지만, 경험적으로 풀어봐야 이해할듯 말듯하고, 원리에 대해 명쾌하게 설명해주는 블로그가 없어서 아쉬웠다. 이 부분은 좀 더 고민해보고 이 포스트에 보충해서 쓰도록 하겠다.