프로그래머스 괄호 변환

·2023년 1월 11일
0

문제

카카오에 신입 개발자로 입사한 "콘"은 선배 개발자로부터 개발역량 강화를 위해 다른 개발자가 작성한 소스 코드를 분석하여 문제점을 발견하고 수정하라는 업무 과제를 받았습니다. 소스를 컴파일하여 로그를 보니 대부분 소스 코드 내 작성된 괄호가 개수는 맞지만 짝이 맞지 않은 형태로 작성되어 오류가 나는 것을 알게 되었습니다.

수정해야 할 소스 파일이 너무 많아서 고민하던 "콘"은 소스 코드에 작성된 모든 괄호를 뽑아서 올바른 순서대로 배치된 괄호 문자열을 알려주는 프로그램을 다음과 같이 개발하려고 합니다.


코드

import java.util.*;
import java.util.stream.*;

class Solution {
    public String solution(String p) {
        //수행한 결과를 그대로 리턴
        return execute(new StringBuilder(p)).toString();
    }
    
    //메인 로직
    public static StringBuilder execute(StringBuilder sb){
        //빈 문자열이면 빈 문자열 리턴
        if(sb.length()==0)
            return sb;
        
        //최소한의 길이의 균형 잡힌 문자열 구하기
        int left=0;
        int right=0;
        for(int i=0; i<sb.length(); i++){
            if(sb.charAt(i)=='(')
                left++;
            else
                right++;
            
            if(left==right)
                break;
        }
        
        //u, v로 나누기
        StringBuilder u=new StringBuilder(sb.substring(0, left+right));
        StringBuilder v=new StringBuilder(sb.substring(left+right, sb.length()));
        
        //u가 올바른 문자열이라면 v에 대해서 메인로직을 수행한 후 덧붙여서 리턴
        if(isCorrect(u)){
            u.append(execute(v));
            return u;
        }
        
        //하라는 대로 실행
        sb=new StringBuilder();
        sb.append('(');
        sb.append(execute(v));
        sb.append(')');
        u.deleteCharAt(0);
        u.deleteCharAt(u.length()-1);
        sb.append(reverse(u));
        
        return sb;
    }
    
    //모든 괄호 문자열을 반대로 뒤집는 메서드
    public static StringBuilder reverse(StringBuilder sb){
        return new StringBuilder(sb.chars()
            .mapToObj(o->{
                if(o=='(')
                    return ")";
                
                return "(";
            })
            .collect(Collectors.joining()));
    }
    
    //올바른 문자열인지 확인하는 메서드(스택 사용)
    public static boolean isCorrect(StringBuilder sb){
        if(sb.charAt(0)==')' || sb.length()%2!=0)
            return false;
        
        Stack<Character> stack=new Stack<>();
        
        for(int i=0; i<sb.length(); i++){
            if(stack.isEmpty()){
                stack.add(sb.charAt(i));
                continue;
            }
            
            if(stack.peek()!=sb.charAt(i))
                stack.pop();
            else
                stack.add(sb.charAt(i));
        }
        
        return stack.isEmpty();
    }
}

해결 과정

  1. 재귀적인 호출을 문제에서 요구하길래 재귀 호출하는 메서드를 만들어서 하라는 대로 구현했다! 카카오 문제 중에서 제일 쉬운 문제였다.

  2. 😁

profile
渽晛

0개의 댓글