[프로그래머스] 문자열 압축 Java

Kang Junhyeok·2024년 9월 26일
post-thumbnail

이번 문제는 2020 KAKAO BLIND RECRUITMENT에서 출제되었고 level 2 문자열 압축 입니다.

문제 설명

데이터 처리 전문가가 되고 싶은 "어피치"는 문자열을 압축하는 방법에 대해 공부를 하고 있습니다. 최근에 대량의 데이터 처리를 위한 간단한 비손실 압축 방법에 대해 공부를 하고 있는데, 문자열에서 같은 값이 연속해서 나타나는 것을 그 문자의 개수와 반복되는 값으로 표현하여 더 짧은 문자열로 줄여서 표현하는 알고리즘을 공부하고 있습니다.
간단한 예로 "aabbaccc"의 경우 "2a2ba3c"(문자가 반복되지 않아 한번만 나타난 경우 1은 생략함)와 같이 표현할 수 있는데, 이러한 방식은 반복되는 문자가 적은 경우 압축률이 낮다는 단점이 있습니다. 예를 들면, "abcabcdede"와 같은 문자열은 전혀 압축되지 않습니다. "어피치"는 이러한 단점을 해결하기 위해 문자열을 1개 이상의 단위로 잘라서 압축하여 더 짧은 문자열로 표현할 수 있는지 방법을 찾아보려고 합니다.

예를 들어, "ababcdcdababcdcd"의 경우 문자를 1개 단위로 자르면 전혀 압축되지 않지만, 2개 단위로 잘라서 압축한다면 "2ab2cd2ab2cd"로 표현할 수 있습니다. 다른 방법으로 8개 단위로 잘라서 압축한다면 "2ababcdcd"로 표현할 수 있으며, 이때가 가장 짧게 압축하여 표현할 수 있는 방법입니다.

다른 예로, "abcabcdede"와 같은 경우, 문자를 2개 단위로 잘라서 압축하면 "abcabc2de"가 되지만, 3개 단위로 자른다면 "2abcdede"가 되어 3개 단위가 가장 짧은 압축 방법이 됩니다. 이때 3개 단위로 자르고 마지막에 남는 문자열은 그대로 붙여주면 됩니다.

압축할 문자열 s가 매개변수로 주어질 때, 위에 설명한 방법으로 1개 이상 단위로 문자열을 잘라 압축하여 표현한 문자열 중 가장 짧은 것의 길이를 return 하도록 solution 함수를 완성해주세요.


제한 사항

s의 길이가 1000이하, 모두 소문자입니다.


입출력 예시


문제 요약(문제가 너무 길어,,,)

Main point 반복되는 문자를 "반복횟수 + 반복되는 문자"로 대체하는데 최대한 짧게 만드는 것이다.


문제 풀이 전 생각 정리

  1. 최소 위해서 최대로 초기화한다. answer를 문자열의 길이로 정하고 시작한다.
  2. 글자를 1 ~ s.length()/2로 순차적으로 잘라서 검사를 진행한다.
    -> substring 사용하면 될 듯
  3. 잘라서 검색하다가 반복이 되지 않으면 "반복횟수 + 반복되는 문자"로 저장한다.
    -> 최소로 만드는 것이 목표이기 때문에 s를 다시 재사용 가능성 있음
  4. 길이가 1인 경우는 그냥 return 1 처리

❗️ 굳이 문자열로 저장해서 문제를 풀어야할까?❗️
아무래도 문자열이 무거우니깐 단순 검사 통해서 하면 어떨까?


코드

import java.util.ArrayList;

class Solution {
    
    public int press(String str, int length) {
        StringBuilder sb = new StringBuilder(); // 줄인 문자열을 저장.
        
        String last = "";
        int count = 0;
        for (int start = 0; start < str.length(); start += length) {
            int end = start + length;
            
            if (end > str.length()) end = str.length(); //길이가 오버돼서 에러나는 경우
            
            String token = str.substring(start, end); //압축할 단위
            
            if (token.equals(last)) count++;
            else {
                if (count > 1) sb.append(count);
                sb.append(last);
                last = token;
                count = 1;
            }
        }
        if (count > 1) sb.append(count); //1은 반복이 아니기 때문에 1보다 큰 값일 경우
        sb.append(last);
        
        return sb.length();
    }
    
    public int solution(String s) {
        int answer = s.length();
        if (s.length() == 1) return 1;
        
        for (int length = 1; length <= s.length()/2; length++) {
            int pressed = press(s, length); // 압축했을 때 문자열의 길이
            if (pressed < answer) { // 최소값 찾기
                answer = pressed;
            }
        }
        
        return answer;
    }
}

개인 소감

코딩 테스트 준비한지 얼마 되지 않아서 생각하는 것도 구현하는 것도 미숙한 부분들이 많다는 느낌을 많이 받았다. 그리고 문제 풀고 나서 개인적으로 문자열을 새롭게 만들어서 결과를 구하는 방법이 메모리 측면에서 비효율적이라는 생각이 들었다. 추후 문자열로 저장하지 않고 단순 검사를 통해서 결과값을 구해볼 예정이다.

to be continue,,,,


0개의 댓글