1, 2, 4로 모든 수를 표현하는 방법.
'숫자가 3개이니 3진법 쓰면 되지 않나?' 라는 생각에서 파생한다면 쉽게 풀 수 있다.
Java로는 3진법으로 값을 구한 뒤 변환하는 방법을, Python으로는 해당 방법을 3진법으로 변환하는 와중 쉽게 값을 뽑는 방법을 소개하겠다.
3진법 수행 후 값을 변환.
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Collectors;
class Solution {
public String solution(int n) {
List<Integer> list = new ArrayList<>();
int val;
while (n != 0) {
list.add(n % 3);
n /= 3;
}
for (int i = 0; i < list.size() - 1; i++) {
val = list.get(i);
if (val <= 0) {
list.set(i+1, list.get(i+1) - 1);
list.set(i, val + 3);
}
}
if (list.get(list.size() - 1) == 0)
list.remove(list.size() - 1);
Collections.reverse(list);
return list.stream()
.map(v -> Integer.toString(v))
.collect(Collectors.joining(""))
.replace("3", "4");
}
}
List<Integer> list = new ArrayList<>();
int val;
3진법 값들을 담을 List와 값을 담을 val 선언.
while (n != 0) {
list.add(n % 3);
n /= 3;
}
n을 3진법으로 변환하여 담는다.
이 때, 순서는 우리가 원하는 방식과 거꾸로임에 주의.
for (int i = 0; i < list.size() - 1; i++) {
val = list.get(i);
if (val <= 0) {
list.set(i+1, list.get(i+1) - 1);
list.set(i, val + 3);
}
}
값을 확인하며 0이 있는지 찾는다.
3진법과 답을 비교할 시, 0이 있다면 해당하는 앞자리에 -1을 수행하고 4가 들어가게 된다.
이처럼 0이 발견된다면 앞자리에서 -1
을 한 후 현재 위치에 +3
을 수행했다(계산의 편의를 위해 4 대신 3을 넣는 방식, 밑에서 3을 4로 변환할 것이다).
if (list.get(list.size() - 1) == 0)
list.remove(list.size() - 1);
Collections.reverse(list);
현재 list 내의 값들은 순서가 뒤집혀져 있다. 즉, 맨 뒷자리가 맨 앞자리로 오게 된다.
혹여나 맨 앞자리로 올 수가 0이라면, 출력하지 않도록 미리 제거했다.
그 후 reverse로 순서를 맞춰줬다.
return list.stream()
.map(v -> Integer.toString(v))
.collect(Collectors.joining(""))
.replace("3", "4");
현재 list의 내부 값은 int 형태이므로, map을 통해 String으로 변환한다.
그 후 join을 통해 하나의 문자열로 만든 후, 아까 계산의 편의를 위해 3으로 넣어줬던 값을 4로 변환하여 return한다.
3진법을 사용하되 더 나은 규칙을 찾아 풀이
def solution(n):
answer = 0
i = 1
while n:
val = n % 3
if val == 0:
answer += 4 * i
n -= 1
else:
answer += val * i
n //= 3
i *= 10
return str(answer)
answer = 0
i = 1
값을 담을 answer와 현재 자릿수인 i를 선언.
while n:
val = n % 3
if val == 0:
answer += 4 * i
n -= 1
else:
answer += val * i
n //= 3
i *= 10
마찬가지로 n % 3
을 통해 3진법의 수를 구한다.
이 때, 현재 구해진 값이 0이라면 값은 4가 들어가야 할 것이고, 다음 값은 -1
이 적용된 형태로 들어가야 한다.
따라서 n -= 1
을 통해 다음에 올 3진법의 수에 미리 -1
을 수행한다.
아니라면 그대로 수행.
그 후 해당하는 자릿수에 값을 넣어준다.
return str(answer)
구한 값을 String으로 형변환하여 반환하면 끝.
풀이만 보면 Java로 풀고, 규칙을 깨달은 후 Python으로 푼 것 같지만.. 실상은 반대다. 현재 Java를 공부하면서 알고리즘을 다시 푸는 중. Python 코드를 보고 깜짝 놀랐다.
n -= 1
은 생각해보면 굳이 0일때만 해 줄 필요는 없다. 0일 때만 효과가 있는 것일 뿐. 따라서 코드를 더 간결하게 만들 수 있다. 좋아요를 가장 많이 받은 코드들을 보면.. 현타가 올 수 있다.
StringBuffer 사용법도 익힐 겸 Java로도 Python 풀이처럼 풀어보았다.
class Solution {
public String solution(int n) {
StringBuffer buff = new StringBuffer();
int d, r;
while (n > 0) {
d = n / 3;
r = n % 3;
if (r == 0) {
r = 4;
d--;
}
buff.append(r);
n = d;
}
return buff.reverse().toString();
}
}