TIL_20250312_진법변환

Kim jisu·2025년 3월 12일

TIL

목록 보기
16/43

오늘의 알고리즘 문제는 숫자를 3진법으로 변환한 후, 이를 다시 10진법으로 변환.

이를 구현하는 동안 내가 시도한 코드와 다른 사람의 풀이를 비교하며 오류와 최적화 포인트를 분석했다.


1️⃣ 3진법 변환 과정

주어진 숫자 n을 3진법으로 변환하는 방법은 나머지 연산(% 3)과 몫 연산(/ 3)을 반복하는 것이다.

🧩 기본 원리

  1. n % 3 → 현재 자리수(나머지)를 구함.
  2. n = n / 3 → 다음 자리수를 위해 몫을 갱신.
  3. 위 과정을 n == 0이 될 때까지 반복.
  4. 나머지를 뒤집어서 저장하면 3진법 변환 결과가 된다.

📝 예제 (n = 45)

45 % 3 = 0  → 0
45 / 3 = 15
15 % 3 = 0  → 0
15 / 3 = 5
5 % 3 = 2   → 2
5 / 3 = 1
1 % 3 = 1   → 1
1 / 3 = 0  (종료)

✅ 3진법 변환 결과 (뒤집힌 상태): 1200


2️⃣ 3진법을 10진법으로 변환

  • 변환된 3진법 숫자는 거꾸로(오른쪽부터) 해석해야 한다.
  • 각 자리수에 3^i를 곱한 후 더하면 된다.

예제 (1200을 10진법으로 변환)

1 × 3^3 + 2 × 3^2 + 0 × 3^1 + 0 × 3^0
= 1 × 27 + 2 × 9 + 0 × 3 + 0 × 1
= 27 + 18 + 0 + 0
= 45

✅ 다시 원래 숫자로 복원됨!


3️⃣ 내가 처음 시도한 코드

import java.util.*;

class Solution {
    public int solution(int n) {
        List<Integer> transNum = new ArrayList<Integer>();

        while (n > 0) {
            int count = 0;
            transNum.add(n % 3);
            n = n / 3;
            count++;
        }

        int answer = 0;
        for (int i = 0; i < transNum.length; i++) {  // ❌ 오류 발생
            answer += 10 ** (i - 1) * transNum.pop();  // ❌ 오류 발생
        }

        return answer;
    }
}

❌ 발생한 오류와 해결책

  1. transNum.length 사용 오류

    • ArrayList<Integer>에는 .length 속성이 없음.
    • ✅ 해결: .size() 사용.
  2. transNum.pop() 사용 오류

    • ArrayList<Integer>는 Stack이 아니므로 .pop()이 없음.
    • ✅ 해결: .remove(transNum.size() - 1) 사용.
  3. `10 (i - 1)` 사용 오류**

    • Java에는 ** 연산자가 없고, 대신 Math.pow(10, i-1)을 사용해야 함.
    • ✅ 해결: Math.pow(10, i-1)로 변경.

4️⃣ 최적화하여 다시 작성한 코드

import java.util.*;

class Solution {
    public int solution(int n) {
        List<Integer> transNum = new ArrayList<>();

        // 3진법 변환 (뒤집힌 상태로 저장)
        while (n > 0) {
            transNum.add(n % 3);
            n = n / 3;
        }

        // 10진법 변환
        int answer = 0;
        int power = 1; // 3의 거듭제곱 (1, 3, 9, 27, ...)
        for (int i = transNum.size() - 1; i >= 0; i--) {
            answer += transNum.get(i) * power;
            power *= 3;
        }

        return answer;
    }
}

✅ 리스트를 사용하여 3진법 변환 후, 10진법으로 변환.
✅ 3의 거듭제곱을 power *= 3로 효율적으로 계산.


5️⃣ 다른 사람의 풀이 분석

class Solution {
    public int solution(int n) {
        String a = "";

        while(n > 0){
            a = (n % 3) + a;  // 3진법 변환 (문자열 이용)
            n /= 3;
        }

        a = new StringBuilder(a).reverse().toString();  // 뒤집기

        return Integer.parseInt(a, 3);  // 3진법 -> 10진법 변환
    }
}

🎯 차이점 및 분석

내 풀이다른 사람 풀이
3진법 변환 방식List<Integer> 사용하여 나머지 저장String을 활용하여 바로 누적
뒤집기 방식List<Integer>를 거꾸로 탐색StringBuilder.reverse() 활용
10진법 변환직접 3^i를 계산Integer.parseInt(a, 3) 활용

🧐 다른 사람 풀이의 장점

✅ 문자열을 사용하여 간결한 구현 가능
✅ Integer.parseInt(a, 3)를 사용하여 10진법 변환을 자동 처리
✅ StringBuilder.reverse()를 활용하여 간단하게 뒤집기 구현


💡 배운 점

✅ 내 방식 (리스트 활용)

  • 리스트를 사용하면 데이터 조작이 용이하므로 가독성이 좋다.
  • 하지만 10진법 변환 시 거듭제곱 연산을 직접 수행해야 하는 단점이 있다.

✅ 다른 사람 방식 (문자열 활용)

  • Integer.parseInt(a, 3)를 사용하면 Java 내부에서 최적화된 방식으로 변환 가능.
  • 문자열 뒤집기(StringBuilder.reverse())를 이용하면 코드가 간결해짐.

🚀 결론

  1. 처음에는 리스트 기반으로 3진법을 변환했지만, 문자열을 이용한 방식이 더 효율적일 수 있음.
  2. Java의 Integer.parseInt(str, base) 기능을 활용하면 변환을 더 쉽게 할 수 있음.
  3. 리스트 기반 방식은 논리적으로 명확하지만, 코드 간결성에서는 문자열 방식이 우수.
  4. 이제는 상황에 따라 List<Integer> 또는 String을 적절히 활용할 수 있게 됨! 🚀

💡 다음에는 다른 진법 변환도 Integer.parseInt(a, base)를 활용해서 풀어봐야겠다! 🎯

profile
Dreamer

0개의 댓글