ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스 / JS] Lv.1 문자열 나누기
    Algorithm/프로그래머스 2022. 12. 20. 17:11
    반응형

    문제 설명

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

     

    • 먼저 첫 글자를 읽습니다. 이 글자를 x라고 합시다.
    • 이제 이 문자열을 왼쪽에서 오른쪽으로 읽어나가면서, x와 x가 아닌 다른 글자들이 나온 횟수를 각각 셉니다. 처음으로 두 횟수가 같아지는 순간 멈추고, 지금까지 읽은 문자열을 분리합니다.
    • s에서 분리한 문자열을 빼고 남은 부분에 대해서 이 과정을 반복합니다. 남은 부분이 없다면 종료합니다.
    • 만약 두 횟수가 다른 상태에서 더 이상 읽을 글자가 없다면, 역시 지금까지 읽은 문자열을 분리하고, 종료합니다.

     

     

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


    제한사항

    • 1 ≤ s의 길이 ≤ 10,000
    • s는 영어 소문자로만 이루어져 있습니다.

     

    풀이

    function solution(s) {   
        let arrStrings = [];
    
        outer: while (true) {
            let x = s[0];
            let numX = 0;
            let numOthers = 0;
    
            for (let i = 0; i < s.length; i++) {
                if (i === s.length - 1) {
                    arrStrings.push(s);
                    break outer;
                    
                } else if (s[i] === x) {
                    numX++;
                    if (numX === numOthers) {
                        arrStrings.push(s.slice(0, i + 1));
                        s = s.slice(i + 1);
                        break;
                    }
                    
                } else {
                    numOthers++;
                    if (numX === numOthers) {
                        arrStrings.push(s.slice(0, i + 1));
                        s = s.slice(i + 1);
                        break;
                    }
                }
            }
        }
        return arrStrings.length;
    }

    실행에 걸린 최대 시간 : 5.1ms

     

    사고과정

    1. 두 횟수가 같아질때마다 s를 갱신하고 잘린 문자열을 담을 배열이 필요하겠다.
    2. for 문을 통해 각 원소에 접근하다가 1의 경우엔 몇몇 변수들의 초기화가 필요한데 어떡게하지?
    3. while로 한 번 더 감싸서 for 문에서 2의 경우 break 될 때마다 변수를 초기화 하면 되겠는데?
    4. for 문에선 선언한 i가 마지막 인덱스가 되면 while까지 한번에 탈출할 수 있도록 라벨링 하자.

     

    평가

      for 문안에서 numX === numOthers 조건문이 중복되었다. 따로 빼놓는게 더 깔끔하다. 또한 굳이 while문까지 쓸 필요가 있었을까? 어차피 개수만 리턴하는 거니까 for문으로 충분할 것 같은데?

     

    개선점

    1. 중복의 제거

    function solution(s) {   
        let arrStrings = [];
    
        outer: while (true) {
            let x = s[0];
            let numX = 0;
            let numOthers = 0;
    
            for (let i = 0; i < s.length; i++) {
                if (i === s.length - 1) {
                    arrStrings.push(s);
                    break outer;
                } else if (s[i] === x) {
                	numX++;
                } else numOthers++;
    
                if (numX === numOthers) {
                    arrStrings.push(s.slice(0, i + 1));
                    s = s.slice(i + 1);
                    break;
                }
                
            }
        }
        return arrStrings.length;
    }

     위 코드와 같이 수정하니 코드 실행에 걸리는 시간의 최대값이 4.89ms로 단축됐다.

     

     

    2. 반복문의 중복을 제거하자

    function solution(s) {   
        let numStr = 0;
        let x = s[0];
        let numX = 0;
        let numOthers = 0;
    
        for (let i = 0; i < s.length; i++) {
            if (i === s.length - 1) {
                numStr++;
                break;
            } 
            else if (s[i] === x) numX++;
            else numOthers++;
            
            if (numX === numOthers) {
                numStr++;
                x = s[i + 1]
                numX = 0;
                numOthers = 0;
                continue;
            }
        }
        return numStr;
    }

    위 코드와 같이 중복을 제거할 경우 시간의 최대값이3.7ms 까지 단축된다.

     

    알게된점

     

     

    반응형

    댓글

Designed by Tistory.