본문 바로가기
Java/알고리즘

N진수 게임

by 티코딩 2023. 10. 30.

점점 알고리즘 문제가 어려워진다. 대충 머리로는 어떻게 풀진 알거같아서 일단 풀어봤는데 벽을 느끼고 포기했다.

내가 먼저 시도했던 수도코드를 보면

// int[] arr = new int[m*t];

// 0부터 arr.length까지반복문돌면서 i를 Integer.toString(i,n) n진수로 변환하고

// n진수로 변환한 i가 2자리 이상일때, 각 자리수를 다시 int로 변환해 arr[]에다가 집어넣는다.

그런데 코드를 짜다 보니 arr[]에 집어넣는 과정이 굉장히 까다로웠다. 그래서 다시 다른 방법으로 풀려다가 벽에 부딪혔다...

같이 문제를 푼 영재님은 JavaScript를 사용해서 푸셨는데, 킹갓 영재님의 풀이를 보자

function solution(n, t, m, p) {
    let numRange = '';
    let result = '';

    for (let i = 0; i < t * m; i++) {
        numRange += i.toString(n).toUpperCase();
    }
    let arr = [...numRange];

    for (let i = p; i < numRange.length; i += m) {
        result += arr[i - 1];
        if (result.length === t) break;
    }
    return result;

numRange라는 문자열을 만들고, n진수로 바꾸고, 10부터 a로 나오기때문에 toUpperCase()로 대문자로 변환시켜서 numRange에 넣었다.

그리고 result에 p번째부터 m단위로 뛰면서 넣었다. 그리고 result길이가 t가 되면 break로 빠져나왔다.

완전 깔끔한데, java로 이걸 구현하려니 자바의 문자열은 저렇게 자유롭지 못해서 어쩌지 싶어서 지피티한테 물어봤더니

지피티가 알려준 코드는 StringBuilder를 사용했다.

StringBuilder는 자바 처음 시작할때, 그때 봤던거같은데 이게 뭔지, 어떤 특징이 있는지도 까먹고 있었다.

일단 코드를 보기 전에, StringBuilder에 대해 알아보자.

지피티한테 물어보니 이렇게 알려줬다.

StringBuilder 클래스의 주요 특징 및 사용법은 다음과 같습니다:

1. 가변성: StringBuilder 객체는 내부적으로 문자열을 가변적으로 처리하므로 문자열을 추가하거나 수정하는 데 사용됩니다.

2. 메서드: StringBuilder 클래스에는 문자열 조작을 위한 다양한 메서드가 포함되어 있습니다. 이러한 메서드를 사용하여 문자열을 추가, 수정, 삭제, 끼워넣기 및 기타 조작 작업을 수행할 수 있습니다.

3. 성능: StringBuilder는 문자열 조작에 사용하는 성능 면에서 효율적입니다. 문자열의 불변성으로 인한 새로운 문자열 객체를 계속 생성하는 비용을 피할 수 있습니다.

4. 스레드 안전성: StringBuilder는 스레드 안전하지 않습니다. 따라서 멀티스레드 환경에서 동시에 접근하려면 추가적인 동기화가 필요합니다. 스레드 안전성을 고려해야 하는 경우 StringBuffer 클래스를 사용할 수 있습니다. StringBuffer는 StringBuilder와 비슷하지만 스레드 안전합니다.

StringBuilder sb = new StringBuilder();

// 문자열 추가
sb.append("Hello, ");
sb.append("World!");

// 문자열 삽입
sb.insert(5, "Java ");

// 문자열 삭제
sb.delete(5, 9);

// 문자열 변경
sb.replace(0, 5, "Hi");

// 문자열 출력
System.out.println(sb.toString()); // "Hi, Java World!"

// 문자열 길이 확인
int length = sb.length(); // 14

// 문자열 초기화
sb.setLength(0); // sb를 비우고 재사용 가능

// 문자열 크기 조절
sb.ensureCapacity(100); // 내부 버퍼 크기 조절

이런 개꿀 기능이 있다니, 생각도 못했다. 이제 문자열을 자유롭게 써야하는 알고리즘 문제가 있을때 StringBuilder를 사용해야겠다.

 

지피티가 알려준 코드

public static String solution(int n, int t, int m, int p) {
        StringBuilder numRange = new StringBuilder();
        StringBuilder result = new StringBuilder();

        for (int i = 0; i < t * m; i++) {
            numRange.append(Integer.toString(i, n).toUpperCase());
        }

        char[] arr = numRange.toString().toCharArray();

        for (int i = p - 1; i < numRange.length(); i += m) {
            result.append(arr[i]);
            if (result.length() == t) {
                break;
            }
        }

        return result.toString();
    }

일단 로직은 영재님이 푼 로직과 정확히 똑같다.

나는 int[] arr로 만들었던걸  numRange를 StringBuilder로 만들고 numRange.append(Integer.toString(i,n).toUpperCase());

하면 16진수로 바꾸면

이런식으로 10부터 15까지는 각 A~F까지가 된다.

그다음 한글자씩 arr에 저장해야하기 때문에 char배열로 만들고 한글자씩 저장한다.

그다음 결과를 도출하기 위해 p가 3일땐 index는 p-1이기 때문에, i를 p-1로 두고, m만큼 간격을 두고 값을 뽑아내야하기 때문에, result에 넣고, result길이가 t가 될때, StringBuilder인 result를 다시 String으로 바꾸고 반환한다.

 

오늘문제는 비록 내힘으로 풀진 못했지만 StringBuilder를 사용한 첫 문제여서 의미가 있었다. 이렇게 푸는 방법도 익숙해져야겠다.

 

ㅇ 다른 분들의 풀이

class Solution {
  public String solution(int n, int t, int m, int p) {
    String answer = "";

    int startNum = 0;

    String targetString = new String();
    String retString = new String();

    while (targetString.length() < m * t) {
        targetString += Integer.toString(startNum++, n);
    }

    for (int i=0; i<t; i++) {
        retString += targetString.charAt(p - 1 + i * m);
    }

      answer = retString.toUpperCase();


      return answer;
  }
}

StringBuilder를 쓰지 않고 풀었다. 로직은 비슷하다. 그런데 저렇게 String 으로 해도되는지 몰랐다. 내가 처음 int형 배열에다가 넣을생각부터가 잘못된거였다. 그냥 String으로 += 해서 넣었어도됐던것이었다. 허무하다.

'Java > 알고리즘' 카테고리의 다른 글

알고리즘 공부(3) - 완전탐색을 알아보자  (1) 2023.10.31
게임 맵 최단거리  (0) 2023.10.31
압축  (0) 2023.10.26
while문의 사용에 익숙해져보자  (0) 2023.10.25
Lv1로 쉬어가기 (5문제)  (0) 2023.10.25