알고리즘 단련장/소프티어

[소프티어] X marks the Spot 레벨2 자바 풀이 (한양대 HCPC 2023)

dcho 2024. 10. 29. 01:52
SMALL

https://softeer.ai/practice/7703

 

Softeer - 현대자동차그룹 SW인재확보플랫폼

 

softeer.ai

 

 

 

생각보다 단순한 문제 같았다.

내가 생각했던 로직은 아래와 같다.

  1. n을 입력받아 총 몇번 반복할지 결정
  2. s[i]에서 x, X 찾고 해당 index를 p 변수에 담기
  3. t[i]에서 p번째 문자 찾기
  4. result에 대문자로 변환한 문자를 추가하기

 

하지만 결과는 시간초과

 

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    public static String[] s;
    public static String[] t;
    public static StringBuffer result = new StringBuffer();
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int n = Integer.parseInt(br.readLine());
        s = new String[n];
        t = new String[n];

        // 방법 1
        //for (int i = 0; i < n; i++) {
        //    StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        //    int p;
        //    s[i] = st.nextToken();
        //
        //    // s[i]에서 x, X 찾기
        //    p = s[i].indexOf('x');
        //    if (p == -1) p = s[i].indexOf('X');
        //
        //    t[i] = st.nextToken();
        //
        //    // t[i]에서 p번째 문자 찾기
        //    char tCharValue = t[i].charAt(p);
        //
        //    // result에 t[i]의 p번째 문자 추가 (대문자로 변환)
        //    result += Character.toUpperCase(tCharValue);
        //}

        // 방법 2
        for (int i = 0; i < n; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine(), " ");
            String stringS = st.nextToken();
            String stringT = st.nextToken();

            // 대문자로 변환
            s[i] = stringS.toUpperCase();
            t[i] = stringT.toUpperCase();

            // s[i]에서 x, X 찾기
            int p = s[i].indexOf('X');

            // t[i]에서 p번째 문자 찾기 및 result에 추가
            result.append(t[i].charAt(p));
        }

        bw.write(result + "\n");
        bw.flush();
        bw.close();
    }
}

 

로직에는 큰 문제는 없었으나 중구난방해서 방법 2로 바꾸었다.

우선 String 인스턴스로 받아서 대문자로 변환 하고 X를 찾아 바로 추가하는 것이였다. 

 

근데.. String 인스턴스로 += 하니까 시간초과가 났었던것. StringBuffer로 바꾸니까 해결이 되었다. 

 

이유는 다음과 같았다.

String 클래스에서 += 연산을 사용하는 것은 비효율적인 이유가 있습니다. String은 immutable(불변) 객체이기 때문에, 문자열을 변경할 때마다 새로운 String 객체가 생성되고, 이전 문자열과 새로운 내용을 합친 결과를 다시 할당하는 방식으로 작동합니다. 이런 과정이 반복되면 매번 새로운 메모리 할당과 문자열 복사가 발생하기 때문에 시간 복잡도가 높아지고 성능이 저하됩니다.

반면에 StringBuffer는 mutable(가변) 객체로, 내부 버퍼를 사용해 문자열을 직접 변경할 수 있습니다. 따라서 문자열 추가 작업이 빈번히 일어나는 경우 StringBuffer는 메모리 재할당 없이 기존 버퍼를 사용하므로 성능이 훨씬 더 효율적입니다.

이를 요약하자면, += 연산으로 문자열을 계속 붙이는 경우 String은 새로운 객체를 반복해서 생성해 시간 초과가 발생하지만, StringBuffer는 기존 버퍼를 활용해 효율적으로 문자열을 조작하므로 시간 초과 문제가 해결됩니다.

 

앞으로 시간초과도 신경써서 해결할 수 있게 되었다.