문자열 뒤집기

남기용·2021년 7월 18일
0

알고리즘

목록 보기
3/4

문자열 알고리즘 문제 풀이에 약점이 있다 느껴 최근 문자열 문제를 풀이하는 중
문자열 뒤집기 문제를 만났다.

문자열 뒤집기는 말그래도 주어진 문자열을 거꾸로 뒤집으면 되는데 직관적으로 생각할 수 있는 알고리즘의 시간 복잡도는 linear한 방법을 사용하게 될 것이므로 O(n)이다.

1번 방법

하지만 문자열이 충분히 긴 경우 이보다 더 짧게 문자열을 뒤집을 방법이 없을까 고민을 해보았다.

2번 방법

문자열 또한 배열이기때문에 문자열의 앞부분부터 맨 뒤에 부분과 바꿔주는 방법을 생각했다.

이런 식으로 생각할 수 있는데 이렇게 하면 O(n)인 것은 동일하지만 내부적으로 n/2 만큼 동작하기 때문에 시간을 더 줄일 수 있다.

또 자바에는 StringBuilder 라이브러리에 reverse라는 메소드를 제공하고 있다. 이를 사용했을 때 linear한 방법과 얼마나 시간 차이가 나는지 알아보았다.

천만개의 단어를 가진 문자열을 뒤집었을 때 결과다.

대충 이정도 차이가 났다. 왜 이런 차이가 났는지 자세히 알아보자.

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/StringBuilder.html#reverse()

자바11 api 문서의 StringBuilder 항목을 보면 알 수 있다. 설명을 읽어 보면 리버스한 문자열의 k번째에 들어가야할 문자는 기존 문자열의 n-k-1의 문자와 같기 때문에 바꿔주는 것으로 얻을 수 있다고 설명하고 있다.

즉, 2번 방법을 사용하고 있음을 알 수 있다.

문자열 뒤집기를 통해 같은 결과를 얻더라도 간단한 휴리스틱 적용으로 시간을 절약할 수 있음을 알아보았다.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;

public class Main {
    static int Answer;
    static int n, m;
    static int[] p, rank, arr;
    static ArrayList<String> ans;

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        String str = "A".repeat(1000000);

        String rstr = "";
        System.out.println("linear swap");
        double start = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();
        for (int i = str.length() - 1; i >= 0; i--) {
            sb.append(str.charAt(i));
        }
        rstr = sb.toString();
        double end = System.currentTimeMillis();
        System.out.println("total spend time: " + String.format("%.20f", end - start));

        System.out.println("use StringBuilder API");
        start = System.currentTimeMillis();
        sb = new StringBuilder(str);
        rstr = sb.reverse().toString();
        end = System.currentTimeMillis();
        System.out.println("total spend time: " + String.format("%.20f", end - start));
        bw.flush();
        bw.close();
        br.close();
    }
}
profile
개인용 공부한 것을 정리하는 블로그입니다.

0개의 댓글