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

문자열 압축

https://school.programmers.co.kr/learn/courses/30/lessons/60057 (opens in a new tab)

내 풀이

import java.util.*;
import java.util.stream.Collectors;
 
class Solution {
    public static HashMap<String, Integer> temp = new HashMap<>();
    public static List<String> comb = new ArrayList<>();
    public static Integer ans = 1000;
 
    public int solution(String s) {
        // 콤비네이션 만들기
        for (int i = 0; i < s.length() + 1; i++) {
            for (int j = i + 1; j < s.length() + 1; j++) {
                String key = s.substring(i, j);
                temp.put(key, 0);
            }
        }
        comb = temp.entrySet()
                .stream()
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        
        for (int i = 0; i < comb.size(); i++) {
            boolean[] visited = new boolean[comb.size()];
            Arrays.fill(visited, false);
            recursion(i, s, 0, visited);
        }
 
        return ans;
    }
 
    public void recursion(Integer i, String s, Integer result, boolean[] visited) {
        String repl = comb.get(i);
        Integer prevLen = s.length();
        s = s.replace(repl, "");
        Integer div = (prevLen - s.length()) / repl.length();
        String divStr = String.valueOf(div);
        if(div != 1) {
            result += divStr.length();
        }
        result += repl.length();
 
        if (s.length() == 0) {
            if (ans > result) {
                ans = result;
                System.out.println(result);
            } else {
                ans = ans;
            }
        }
 
        for (int ni = 0; ni < comb.size(); ni++) {
            String newRepl = comb.get(ni);
            if (s.contains(newRepl) && !visited[ni]) {
                visited[ni] = true;
                recursion(ni, s, result,visited);
            }
        }
    }
}

정답 풀이

class Solution {
    public int solution(String s) {
        int answer = s.length();
 
        // 문자열의 반절 이상은 압축하는 의미가 없다.
        for (int i = 1; i <= s.length() / 2; i++) {
            String a = compress(s, i);
 
            answer = Math.min(answer, a.length());
        }
 
        return answer;
    }
 
    private String compress(String s, int num) {
        int count = 1;
 
        String pattern = s.substring(0, num);
 
        StringBuilder builder = new StringBuilder();
 
        for (int i = num; i < s.length(); i += num) {
            // 비교 인덱스가 s의 길이보다 길어질 경우
            if (i + num > s.length()) {
                // 애초에 압축이 불가능하므로 넘어감
 
                builder.append(s.substring(i));
            }
 
            // 아닐 경우
            else {
                String target = s.substring(i, i + num);
 
                // 문자열과 패턴이 동일할 경우
                if (target.equals(pattern)) {
                    count++;
                }
 
                // 동일하지 않을 경우
                else {
                    // 2회 이상 압축이 가능할 경우
                    if (count > 1) {
                        builder.append(count);
 
                        count = 1;
                    }
 
                    builder.append(pattern);
 
                    // 패턴 갱신
                    pattern = target;
                }
            }
        }
 
        // 2회 이상 압축이 가능할 경우
        if (count > 1) {
            builder.append(count);
        }
 
        builder.append(pattern);
 
        return builder.toString();
    }
}

Reference