[프로그래머스][Level2][Java] 괄호 변환

2022. 5. 17. 19:48·프로그래머스/Level 2

문제

문제가 길어서 따로 문제 링크를 첨부

https://programmers.co.kr/learn/courses/30/lessons/60058

 

코딩테스트 연습 - 괄호 변환

카카오에 신입 개발자로 입사한 "콘"은 선배 개발자로부터 개발역량 강화를 위해 다른 개발자가 작성한 소스 코드를 분석하여 문제점을 발견하고 수정하라는 업무 과제를 받았습니다. 소스를

programmers.co.kr

문제의 핵심

풀이 코드

풀이 코드가 길어서 부분부분으로 나눠서 설명 후 전체코드를 올리겠다.

우선, 이 문제를 난 4개의 메서드로 나누었다.

1. 올바른 괄호인지 판단하는 메서드

2. 올바른 괄호가 아닐때, 올바른 괄호로 바꿔주는 메서드

3. 문제의 4-4단계를 실행하는 메서드

4. 1,2,3단계를 통합해서 실행할 solution 메서드

위와 같이 메서드를 나눈 이유는 문제를 풀때, 재귀를 사용해야 되는 경우도 있어서 나눠서 푸는 것이 좋을 것 같아서이다.

 

1. 올바른 괄호인지 판단하는 메서드

public static boolean check(String s) {  //올바른 괄호 판단
    int cnt = 0;
    for (int i = 0; i < s.length(); i++) {
        if (s.charAt(i) == '(') {         // (일경우 cnt+1
            cnt++;
        } else {                          // )일경우 cnt-1
            cnt--;
            if (cnt < 0) {                  // )를 만나서 cnt-1했을 때, cnt가 0보다 작으면 )가 더 많다는 뜻이므로 false return
                return false;
            }
        }
    }                                   // 위의 케이스를 다 통과한 경우 true return
    return true;
}

설명은 주석에 있으므로 자세한 설명은 생략

 

2. 올바른 괄호가 아닐때, 올바른 괄호로 바꿔주는 메서드

public static String split(String tmp) { //u,v로 나눈 뒤, 다시 합침
    int cnt = 0;
    String u = "";
    String v = "";
    if (tmp.length() == 0) {            //빈 문자열일 때, 빈 문자열 return
        return "";
    }
    for (int i = 0; i < tmp.length(); i++) {
        if (tmp.charAt(i) == '(') {     // check메서드와 마찬가지로 (일때 +, )일때 -를 cnt에 해줌
            cnt++;
        } else {
            cnt--;
        }
        if (cnt == 0) {                 // cnt가 0이란 말은 처음부터 i번째까지가 균형잡힌 문자열이란 말임
            u = tmp.substring(0, i + 1);    // 그때 u에 균형잡힌 문자열을 넣고
            v = tmp.substring(i + 1);       // 나머지를 v에 넣는다.
            if (check(u)) {          // u가 균형잡힌 문자열이고 올바른 문자열 일때,
                u = u + split(v);    // u에 v를 재귀시켜서 다시 넣어준다.(3단계 실행)
            }else{                  // u가 균형잡힌 문자열이지만 올바른 문자열이 아닐 때,
                String emp = "";
                emp = "(" + emp + split(v) + ")" + reverse(u);  // 4단계를 그대로 실행
                return emp;
            }
            //블로그에 자세한 설명 기재 - 1
            break;
        }
    }
    return u;
}

여기서 다른 것은 설명을 해놓았지만 break를 걸어둔 이유에 대해서 설명을 하자면

위의 코드에서 균형잡힌 문자열을 u에 넣고 나머지를 v에 넣고 재귀를 사용해서 균형잡힌 문자열을 다시 split함수에 넣어서 푼다. 즉, 균형잡힌 문자열을 한 번 구하고 나머지는 재귀로 푸는 형식인데 break를 걸어주지 않으면 균형잡힌 문자열을 한 번 구하고 반복문에 의해서 또 그다음 균형잡힌 문자열을 또 구해서 또 재귀를 돌리기 때문에 원래 구하려던 문자열에서 이상하게 더 괄호가 늘어나기 때문에 꼭 break를 한번 걸어줘야 한다.

 

3. 문제의 4-4단계를 실행하는 메서드

public static String reverse(String s) { //u 변환
    String tmp = "";
    if(s.length()==0){  //빈 문자열일 경우, 빈 문자열 반환
        return "";
    }else {             // u의 제일 처음과 끝을 제거한 후, ( -> )로, ) -> (로 바꿔준다.
        s = s.substring(1, s.length() - 1);
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                tmp += ")";
            }else{
                tmp += "(";
            }
        }
        return tmp;
    }
}

여기서 좀 실수한 것이 문제를 잘못이해해서

u의 첫 번째와 마지막 문자를 제거하고, 나머지 문자열의 괄호 방향을 뒤집어서 뒤에 붙입니다.

이 말이 u의 앞뒤를 뒤집는 즉, "())()(" 이것이면 앞뒤를 뒤집어서 "()())("이렇게 바꾸라는 말인줄 알고 StringBuilder.reverse를 사용해서 뒤집었는데 알고보니

) -> (이렇게 바꾸고 ) -> ( 이렇게 뒤집으란 소리였다...

즉, "())()(" 이것이면 ")(()()"이렇게 바꾸라는 소리였다...그것도 모르고 한참을 헤맸다...

 

4. 1,2,3단계를 통합해서 실행할 solution 메서드

public String solution(String p) {  //답
    String answer = "";
    if(check(p)){                   //올바룬 문자열일 경우, 그대로 반환
        return p;
    }else{                          //올바른 문자열이 아닌 경우
        answer = split(p);          //split을 통해 문자열을 교정해준다.
    }
    return answer;
}

 

1,2,3,4를 다 합친 전체 코드

public static boolean check(String s) {  //올바른 괄호 판단
    int cnt = 0;
    for (int i = 0; i < s.length(); i++) {
        if (s.charAt(i) == '(') {         // (일경우 cnt+1
            cnt++;
        } else {                          // )일경우 cnt-1
            cnt--;
            if (cnt < 0) {                  // )를 만나서 cnt-1했을 때, cnt가 0보다 작으면 )가 더 많다는 뜻이므로 false return
                return false;
            }
        }
    }                                   // 위의 케이스를 다 통과한 경우 true return
    return true;
}

public static String split(String tmp) { //u,v로 나눈 뒤, 다시 합침
    int cnt = 0;
    String u = "";
    String v = "";
    if (tmp.length() == 0) {            //빈 문자열일 때, 빈 문자열 return
        return "";
    }
    for (int i = 0; i < tmp.length(); i++) {
        if (tmp.charAt(i) == '(') {     // check메서드와 마찬가지로 (일때 +, )일때 -를 cnt에 해줌
            cnt++;
        } else {
            cnt--;
        }
        if (cnt == 0) {                 // cnt가 0이란 말은 처음부터 i번째까지가 균형잡힌 문자열이란 말임
            u = tmp.substring(0, i + 1);    // 그때 u에 균형잡힌 문자열을 넣고
            v = tmp.substring(i + 1);       // 나머지를 v에 넣는다.
            if (check(u)) {          // u가 균형잡힌 문자열이고 올바른 문자열 일때,
                u = u + split(v);    // u에 v를 재귀시켜서 다시 넣어준다.(3단계 실행)
            }else{                  // u가 균형잡힌 문자열이지만 올바른 문자열이 아닐 때,
                String emp = "";
                emp = "(" + emp + split(v) + ")" + reverse(u);  // 4단계를 그대로 실행
                return emp;
            }
            //블로그에 자세한 설명 기재 - 1
            break;
        }
    }
    return u;
}

public static String reverse(String s) { //u 변환
    String tmp = "";
    if(s.length()==0){  //빈 문자열일 경우, 빈 문자열 반환
        return "";
    }else {             // u의 제일 처음과 끝을 제거한 후, ( -> )로, ) -> (로 바꿔준다.
        s = s.substring(1, s.length() - 1);
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                tmp += ")";
            }else{
                tmp += "(";
            }
        }
        return tmp;
    }
}


public String solution(String p) {  //답
    String answer = "";
    if(check(p)){                   //올바룬 문자열일 경우, 그대로 반환
        return p;
    }else{                          //올바른 문자열이 아닌 경우
        answer = split(p);          //split을 통해 문자열을 교정해준다.
    }
    return answer;
}

public static void main(String[] args) {    //테스트 케이스
    Solution31 test = new Solution31();
    String s = "()))((()";
    System.out.println(test.solution(s));
}

 

저작자표시 비영리 (새창열림)

'프로그래머스 > Level 2' 카테고리의 다른 글

[프로그래머스][Level2][Java] 2xn 타일링  (0) 2022.06.04
[프로그래머스][Level2][Java] 모음사전  (0) 2022.05.22
[프로그래머스][Level2][Java] 위장  (0) 2022.05.17
[프로그래머스][Level2][Java] 튜플  (0) 2022.04.14
[프로그래머스][Level2][Java] 짝지어 제거하기  (0) 2022.04.14
'프로그래머스/Level 2' 카테고리의 다른 글
  • [프로그래머스][Level2][Java] 2xn 타일링
  • [프로그래머스][Level2][Java] 모음사전
  • [프로그래머스][Level2][Java] 위장
  • [프로그래머스][Level2][Java] 튜플
BvrPark
BvrPark
코드 퍼즐과 개발 일상
  • BvrPark
    비버의 개발 일지
    BvrPark
  • 전체
    오늘
    어제
    • 분류 전체보기 (121)
      • JAVA (7)
        • 메서드 외울 것 (2)
      • 프로그래머스 (56)
        • 총 풀이 코드(깃허브) (1)
        • Level 1 (22)
        • Level 2 (33)
      • 백준 알고리즘(단계 별) (16)
        • 총 풀이 코드(깃허브) (1)
        • 1. 입출력과 사칙연산 (2)
        • 2. if 문 (2)
        • 3. for문 (1)
        • 4. while문 (2)
        • 5. 1차원 배열 (3)
        • 6. 함수 (1)
        • 7. 문자열 (1)
        • 8. 기본수학 1 (3)
      • 백준 알고리즘(solved.ac) (9)
        • 총 풀이 코드(깃허브) (1)
        • class2 (8)
      • LeetCode 문제 풀이 (4)
        • 총 풀이 코드(깃허브) (1)
        • Easy (3)
      • 코드업 알고리즘 (7)
      • git과 github사용법 (4)
      • html, css, javaScript (2)
      • 프로젝트 (11)
        • 순수 Java 프로젝트 (2)
        • 쇼핑몰 프로젝트 (2)
        • 게시판 프로젝트 (5)
        • 근태관리 프로젝트 (2)
      • 커피타임 (2)
        • 2023년 (2)
        • 2024년 (0)
  • 블로그 메뉴

    • 링크

      • 포트폴리오
      • 깃허브
    • 공지사항

    • 인기 글

    • 태그

    • 최근 댓글

    • 최근 글

    • Designed By정상우
    BvrPark
    [프로그래머스][Level2][Java] 괄호 변환
    상단으로

    티스토리툴바