짝지어 제거하기
문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/12973
문제에 대한 내용
문제 설명
짝지어 제거하기는, 알파벳 소문자로 이루어진 문자열을 가지고 시작합니다. 먼저 문자열에서 같은 알파벳이 2개 붙어 있는 짝을 찾습니다. 그다음, 그 둘을 제거한 뒤, 앞뒤로 문자열을 이어 붙입니다. 이 과정을 반복해서 문자열을 모두 제거한다면 짝지어 제거하기가 종료됩니다. 문자열 S가 주어졌을 때, 짝지어 제거하기를 성공적으로 수행할 수 있는지 반환하는 함수를 완성해 주세요. 성공적으로 수행할 수 있으면 1을, 아닐 경우 0을 리턴해주면 됩니다.
예를 들어, 문자열 S = baabaa
라면
b aa baa → bb aa → aa →
의 순서로 문자열을 모두 제거할 수 있으므로 1을 반환합니다.
제한 조건
- 문자열의 길이 : 1,000,000이하의 자연수
- 문자열은 모두 소문자로 이루어져 있습니다.
입출력 예
s | result |
---|---|
baabaa | 1 |
cdcd | 0 |
입출력 예 설명
입출력 예 #1
위의 예시와 같습니다.
입출력 예 #2
문자열이 남아있지만 짝지어 제거할 수 있는 문자열이 더 이상 존재하지 않기 때문에 0을 반환합니다.
접근 방식
- 현재 문자와 다음 문자를 비교한다.
- 같으면 다음으로 넘어가고, 틀린 경우 현재 문자를 저장한다.
- 2번을 진행하고 저장된 문자열과 진행하기 전의 문자열이 같으면 짝이 없다는 것이므로 로직을 종료하고 1을 리턴한다.
- 다르다면 2,3번을 문자열의 길이가 1이 아닐 때까지 반복한다.
잘못된 접근
class Solution
{
public int solution(String s)
{
boolean flag = false;
StringBuilder tmp = new StringBuilder();
StringBuilder S = new StringBuilder(s);
while(S.length() > 1){
for(int i=0; i<S.length()-1 && flag==false; i++){
if (S.charAt(i) != S.charAt(i+1)) {
if (i==s.length()-2){
tmp.append(S.charAt(i)+S.charAt(i+1));
} else {
tmp.append(S.charAt(i));
}
} else {
for (int j=i+2; j<S.length(); j++){
tmp.append(S.charAt(j));
}
flag = true;
}
}
if(S.length() == tmp.length()) break;
S.setLength(0);
S.append(tmp.toString());
tmp.setLength(0);
flag = false;
}
return S.length() == 0 ? 1 : 0;
}
}
좀 복잡해 보이지만, 앞서 설명했던 접근 방식을 코드화한 것이다.
하지만 결과는, 시간 초과…
주어진 테스트 케이스는 통과했지만, 문자열의 길이가 최대 10만이기 때문에 시간 복잡도가 O(n^2)에 따라 시간 초과가 일어났다.
이후에 1시간 정도 코드를 바꿔봤으나, 도저히 답이 나오지 않아 AI의 도움을 받았다.
Stack이라는 자료구조를 이용해서 손쉽게 풀 수 있었다.
결과
소스 코드
import java.util.*;
class Solution
{
public int solution(String s)
{
Stack<Character> stack = new Stack<>();
for (char t:s.toCharArray()){
if (!stack.isEmpty() && stack.peek() == t) stack.pop();
else stack.push(t);
}
return stack.isEmpty() ? 1 : 0;
}
}
- 주어진 문자열을 forEach를 돌립니다.
- 만약 stack이 비어있지 않고, 스택에서 꺼낸 값이 t와 같다면, pop합니다. (같다는 것은 두 알파벳이 붙어있는 짝이라는 것)
- 다르다면, stack에 추가합니다.
- forEach가 끝나고, 삼항연산자를 통해 stack이 비어있다면(모든 알파벳이 짝이 있다면) 1을, 비어있지 않다면(짝이 없는 알파벳이 존재한다면) 0을 리턴합니다.
결과 이미지
알게 된 점
짝을 지어야 하는 경우에는, stack을 이용하여 간단하게 풀 수 있다.
stack이라는 힌트를 얻고 풀면서, 예전에 올바른 수식 찾기 (괄호가 짝지어진)를 풀었던 기억이 떠올랐다. 괄호 짝짓기의 경우도 똑같이 stack을 이용해서 간단하게 풀 수 있다.