[프로그래머스] Lv.1 문자열 나누기

이진이·2023년 8월 10일
0

⚠️JAVA 언어를 사용합니다.

무려 이 문제를 2시간 반이나 잡고있었다...
이유는 문제를 잘못 해석해서🥲


🔒문제

문자열 s가 입력되었을 때 다음 규칙을 따라서 이 문자열을 여러 문자열로 분해하려고 합니다.

  • 먼저 첫 글자를 읽습니다. 이 글자를 x라고 합시다.

  • 이제 이 문자열을 왼쪽에서 오른쪽으로 읽어나가면서, x와 x가 아닌 다른 글자들이 나온 횟수를 각각 셉니다. 처음으로 두 횟수가 같아지는 순간 멈추고, 지금까지 읽은 문자열을 분리합니다.

  • s에서 분리한 문자열을 빼고 남은 부분에 대해서 이 과정을 반복합니다. 남은 부분이 없다면 종료합니다.

  • 만약 두 횟수가 다른 상태에서 더 이상 읽을 글자가 없다면, 역시 지금까지 읽은 문자열을 분리하고, 종료합니다.

문자열 s가 매개변수로 주어질 때, 위 과정과 같이 문자열들로 분해하고, 분해한 문자열의 개수를 return 하는 함수 solution을 완성하세요.




🗝️정답

class Solution {
    public int solution(String s) {
        int answer = 0;
        int xcnt = 0;
        int ycnt = 0;
        
        char[] str = s.toCharArray();
        char x = str[0];
        
        for(int i=0; i<str.length; i++){
            if(xcnt==0){
                x = str[i];
                xcnt++;
                continue;
            }else if(str[i]==x){
                xcnt++;
            }else{
                ycnt++;
            }
            if(xcnt == ycnt){
                answer++;
                xcnt = 0;
                ycnt = 0;
            }
        }
        if(xcnt!=0)
            answer++;
        
        return answer;
    }
}



💡풀이해석

- 왼쪽부터 읽으면서 첫 글자인 x의 개수와 x가 아닌 모든 글자들의 개수가 같아질 때 문자열을 끊고 카운팅(+1)한다.

- 끊고난 이후 문자열부터 또 반복한다.

- 마지막 짜투리 남아도 카운팅(+1).

// 변수 선언

  • int answer : 카운팅할 변수, 답 저장
  • int xcnt : x가 나온 횟수 저장
  • int ycnt : y가 나온 횟수 저장

// 기초 작업

  • char[] str : 문자열을 한 글자씩 미리 잘라서 배열로 만들어 놓기
  • char x : 첫 글자 초기화

//반복문으로 한글자씩 카운팅

  • if(xcnt==0) : x가 0이면 문자열의 시작이므로 x값 초기화, xcnt 카운팅 이후 더이상 반복문을 돌지 않고 다음 글자로 continue;

  • else if(str[i]==x) : 현재 글자가 x라면 xcnt 카운팅

  • else : 현재 글자가 x가 아니면 ycnt로 카운팅

  • if(xcnt == ycnt) : 현재 글자 카운팅 이후 x개수와 y개수가 같다면 문자열을 끊기. answer을 카운팅 한 후 xcnt, ycnt 초기화

//짜투리 검사

  • if(xcnt != 0) : 딱 떨어지게 문자열이 끝났다면 x의 개수는 초기화된 값인 0이어야 됨. 아니라면 짜투리가 남은 것이므로 answer 한번 더 카운팅




✏️자기 분석

문제를 잘못 이해해서 처음엔 등장하는 알파벳 각각의 합이 하나라도 같아질 때 끊는 줄 알았다.

헷갈리게 하는데 예제도 한 몫 했다...

그래서 진짜 헛짓거리 했다.

하지만 언젠가 이런 문제가 나올 수도 있으니까 새로운 문제를 하나 더 푼 셈 치려고 한다.


만약 문제가 다음과 같았다면,

- 왼쪽부터 읽으면서 문자열에 포함된 알파벳 중 두 개의 개수가 같아지는 순간이 오면 문자열을 끊고 카운팅(+1)한다.

- 끊고 난 이후 문자열부터 또 반복한다.

- 마지막 짜투리 남아도 카운팅(+1).


각각의 문자들을 저장해야 하고, 그 저장한 값에 따른 카운팅도 있어야 한다. 여기까지만 보면 알파벳을 담은 배열을 사용해도 된다.
하지만 그 값이 저장된 다른 값들과 모두 비교하였을 때 같으면 문자열을 자르고 다시 시작해야 하므로 26번의 반복을 계속 해야된다고 생각해서 map을 선택했다.
map에 지금까지 나온 알파벳을 키로 두고 값을 하나씩 증가해 간다면 괜찮을 줄 알았다. 


하지만 map을 쓰려고 하니 각 상황마다 할 일이 너무 달라서 조건문을 아주 많이 사용하였다. 그나마 시간을 줄이기 위해 아래쪽에서는 map에 저장된 알파벳이 하나일때, 각 글자들의 개수를 비교하는 문장을 피하도록 했다.

import java.util.*;

class Solution {
    public int solution(String s) {
        int answer = 0;
        char[] str = s.toCharArray();
        Map<String, Integer> map = new HashMap<> ();
        
        for(int i=1; i<str.length; i++){            
            if(!str[i-1].equals(str[i])){
                if(map.size()==0){
                    answer++;
                    i++;
                    if(i==str.length-1){
                        answer++;
                        break;
                    }
                    map = new HashMap<>();
                    continue;
                } else if(!map.containsKey(str[i])){
                    map.put(str[i], 1);
                } else {
                    map.put(str[i], map.get(str[i])+1);
                }
            } else {
                if(!map.containsKey(str[i])){
                    map.put(str[i], 2);
                } else {
                    map.put(str[i], map.get(str[i])+1);
                }
            }
            if(map.size()>1){
                Set<String> key = map.keySet();
                for(String k : key){
                    if(k.equals(str[i])) continue;
                    if(map.get(k) == map.get(str[i])){
                        answer++;
                        i++;
                        map = new HashMap<>();
                        break;
                    }
                }
            }
        }
        
        return answer;
    }
}

채점을 하는 데 너무 이상해서 문제를 다시 보고 다시 풀었지만, 역시나 문제를 제대로 보지 않아서 다음 풀이가 나왔다...


이번엔 Set과 배열을 사용했다. 각 알파벳을 배열로 카운팅 하고, 그 값을 Set에 넣어준다. 그 카운팅 된 값이 이미 Set에 없다면 하나 카운팅 된 값으로 값을 바꿔주어야 하기 때문에 현재 값을 set에 넣고, 하나 작은 값을 set에서 제거해 준다. 만약 값이 이미 Set에 있다면 알파벳의 개수가 같아진 순간이므로 문자열을 끊고, answer을 카운팅 한 후 초기화한다.
import java.util.*;

class Solution {
    public int solution(String s) {
        int answer = 0;
        char[] str = s.toCharArray();
        
        Set<Integer> cntSet = new HashSet<> ();
        int alp[] = new int[26];
        Arrays.fill(alp, 0);
        for(char ch: str){
            System.out.println((ch-'a') +" 번째 값 = "+alp[ch-'a']);
            alp[ch-'a']++;
            if(cntSet.add(alp[ch-'a'])){
                cntSet.remove(alp[ch-'a']-1);
                System.out.println("true!! "+ch+"="+alp[ch-'a']);
            } else{
                answer++;
                Arrays.fill(alp, 0);
                cntSet = new HashSet<> ();
            }
        }
        if(cntSet.size()>0)
            answer++;
         
        return answer;
    }
}

이 문제에 대한 테스트 케이스는 없으므로 이것도 맞는 풀이인지는 모르겠지만, 일단은 이런 문제가 있을 수도 있는데 시간을 버렸다고 생각하기엔 아까워서 기록하였다.


결론

1. 문제 잘 읽고 잘 해석하는 연습하기

2. 문제 풀다가 오래걸리면 질문목록 꼭 확인하기 == 고집부리지 말기

3. 문제를 잘못 해석한거지만, 다른 문제 하나 더 풀었다고 생각한 점은 기특하다.

profile
프론트엔드 공부합니다. 블로그 이전: https://jinijana.tistory.com

0개의 댓글