코테/프로그래머스

[프로그래머스/C#] 문자열 나누기

내꺼블로그 2024. 3. 13. 11:38

문제


https://school.programmers.co.kr/learn/courses/30/lessons/140108

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

 

 

코드


using System;

public class Solution {
    public int solution(string s) {
        int answer = 0;
        int cnt = 0;
        char c = '1';
        for(int i=0;i<s.Length;i++){
            if(cnt==0){
                c=s[i];
                cnt++;
                answer++;
            }
            else{
                if(s[i]==c)
                    cnt++;
                else{
                    cnt--;
                }
            }
        }
        return answer;
    }
}

 

 

 

풀이


사실 푸는 것보다도 문제 해석에 시간이 더 걸렸다.

예시를 들어 설명 start!

 

요 녀석을 설명해보겠다.

 

처음 문자가 a이므로 a를 기준으로 같은 문자와 다른 문자를 카운트하는 것이다.

0번째 문자는 a이므로 a와 같기 때문에 같은 문자취급하여 같은문자개수를 카운트.

 

1번째도 이하동문

2번째도 이하동문

현재 같은 문자 카운트된 개수는 3개, 다른 문자 카운트된 개수는 0개

 

3번째에서는 a와 다른 b가 나왔으므로 다른 문자 개수 카운트. 그러나 아직 같은 문자 개수와 다른 문자 개수가 다르므로 여전히 문자 a와 비교

 

4번째도 b와 a는 다르므로 다른문자개수 카운트

5번째는 a가 나왔으므로 같은문자개수 카운트

6번째는 a와 다른 c의 등장으로 다른문자개수 카운트 아직 같은문자 4개 다른문자 3개이므로 여전히 a와 비교해야 함.

 

7번째는 또 a와 다른 c가 나왔는데 이때 같은문자개수와 다른문자개수가 같아지는 지점이므로 문자열 분리. 8번째가 첫번째가 되면서 새로 시작.

이제는 다음 문자 c를 기준으로 다시 카운트하면서 문자열 분리 개수를 세면 됨.

 

 

 

 

필자의 경우 어차피 개수만 세면 되므로 문자열을 따로 분리하지는 않고 문제를 풂.

cnt라는 변수를 두어 같은 문자를 만날 때는 ++, 다른 문자를 만났을 때는 --하는 형태로 구현.

(0이 되면 같은문자개수와 다른문자개수가 같아지는 거니까!)

 

cnt값이 0일 경우 새로운 시작을 의미하므로 미리 비교용으로 선언한 문자 c에 해당 문자 할당하고 문자열 하나가 반드시 분리되는 상황이므로 answer값을 1증가.

 

 

cnt값이 0이 아닐 경우 문자열을 분리중인 상태이므로 현재 해당 문자가 c와 같을 경우 cnt값을 1증가, 다를 경우 cnt값을 1감소.

cnt가 감소되어 0이 될 경우 해당 문자 까지 문자열이 분리되는 것을 의미하며 다음 루프 때는 cnt==0의 조건문으로 넘어가 새로운 문자열 분리를 시작하게 됨.

 

 

 

다른 사람 풀이


(1) cnt1, cnt2를 두어 각각을 count하여 비교한 경우. +Remove 사용.

using System;

public class Solution {
    public int solution(string s) {
        int answer = 0;
        int cnt1 = 0;
        int cnt2 = 0;

        char first = s[0];
        s = s.Remove(0,1);
        cnt1++;
        if (s.Length == 0) answer++;

        while(s.Length > 0)
        {
            if(first == s[0]) cnt1++;
            else cnt2++;
            s = s.Remove(0,1);

            if(cnt1 == cnt2)
            {
                answer++;
                if(s.Length > 0)
                {
                    cnt1=0;
                    cnt2=0;
                    first = s[0];
                    s = s.Remove(0,1);
                    cnt1++;
                    if (s.Length == 0) answer++;
                }
            }
            else
            {
                 if (s.Length == 0) answer++;
            }
        }

        return answer;
    }
}

 

Remove로 비교한 문자 하나하나 제거하면서 비교 대상 문자와 0번째 문자를 비교. 같으면 cnt1++, 다르면 cnt2++

cnt1과 cnt2가 같으면 answer++, cnt1과 cnt2 값을 0으로 갱신, first(문자)를 s[0]으로 갱신하고 cnt1++ 다시 또 Remove.

만약 끝까지 다 돌았다면 그 문자를 끝으로 문자열이 분리된 것이므로 answer++

 

 

 

(2) 위와 비슷하지만 Remove는 사용하지 않은 case.

using System;

public class Solution {
    public int solution(string s) {
        int answer = 0;

        if (s == string.Empty)
                return answer;

            char frist = s[0];

            int sameCount = 0;
            int diffCount = 0;

            for (int i = 0; i < s.Length; ++i)
            {
                if(sameCount == 0)
                    frist = s[i];

                if (frist == s[i])
                    sameCount++;
                else
                    diffCount++;

                if (sameCount == diffCount)
                {
                    answer++;

                    sameCount = 0;
                    diffCount = 0;
                }
                else
                {
                    if(i + 1 >= s.Length)
                        answer++;
                }
            }


        return answer;
    }
}

 

for문을 돌며 같은 문자면 sameCount++, 다른 문자면 diffCount++.

sameCount와 diffCount가 같아지는 시점에는 answer++, sameCount와 diffCount는 0으로 갱신.

sameCount가 0이면 현재 해당 문자를 first(비교해야 하는 문자)로 선언.

문자열을 다 돌았다면 answer++