문제링크
https://programmers.co.kr/learn/courses/30/lessons/60058
문제풀이
👨🏻💻 핵심 스킬 👨🏻💻
구현, 시뮬레이션
괄호변환 문제는 괄호를 올바르게 만드는 과정을 구현하는 문제이다. 문제에서는 괄호를 올바르게 변경하는 방법에 대하여 알려주고 있으므로 알려주는 알고리즘을 구현해주기만 하면 된다.
1. 입력이 빈 문자열인 경우, 빈 문자열을 반환합니다.
2. 문자열 w를 두 "균형잡힌 괄호 문자열" u, v로 분리합니다. 단, u는 "균형잡힌 괄호 문자열"로 더 이상 분리할 수 없어야 하며, v는 빈 문자열이 될 수 있습니다.
3. 문자열 u가 "올바른 괄호 문자열" 이라면 문자열 v에 대해 1단계부터 다시 수행합니다.
3-1. 수행한 결과 문자열을 u에 이어 붙인 후 반환합니다.
4. 문자열 u가 "올바른 괄호 문자열"이 아니라면 아래 과정을 수행합니다.
4-1. 빈 문자열에 첫 번째 문자로 '('를 붙입니다.
4-2. 문자열 v에 대해 1단계부터 재귀적으로 수행한 결과 문자열을 이어 붙입니다.
4-3. ')'를 다시 붙입니다.
4-4. u의 첫 번째와 마지막 문자를 제거하고, 나머지 문자열의 괄호 방향을 뒤집어서 뒤에 붙입니다.
4-5. 생성된 문자열을 반환합니다.
문제에서 제시하는 위 1번부터 4번의 과정을 순서대로 구현해주기만 하면 된다. 이 때 문자를 구할 때 재귀를 사용해주면 된다.
if(input.length() == 0)
return "";
1. 빈 문자열인지 확인하고 리턴만 해주면 된다.
int checkPoint = 0;
int find = 0;
Stack<Character> stack = new Stack<>();
do{
stack.add(input.charAt(checkPoint));
if(input.charAt(checkPoint++) == '(')
find++;
else
find--;
}while (find != 0);
2. 문자열을 u와 v로 쪼개어주는데 u는 최소한의 괄호의 수가 맞는 경우이다. 이 때 괄호가 올바르지는 않아도 되며 열린 괄호와 닫힌 괄호의 개수가 동일해지는 최소 위치를 찍어주면 된다. 나는 find라는 변수를 두고 그 값이 '(' 일 경우 +1을 해주고 ')'의 경우 -1을 해주어 0이 될 때를 찾기로 하였다. 이 때 값을 체크하는 checkPoint 변수를 지정하여 최종적으로 균형잡힌 괄호의 값인 u를 구할수 있게 된다.
int closeCount = 0;
boolean isRight = true;
while (!stack.isEmpty()){
char p = stack.pop();
if(p == ')')
closeCount ++;
else
closeCount --;
if(closeCount < 0){
isRight = false;
break;
}
}
3. 위에서 구한 u의 값이 올바른 괄호 문자열인지 확인하는 과정이다. 올바른 괄호의 경우 우측에서부터 좌측으로 확인할 때 닫는 괄호의 개수가 여는 괄호보다 많거나 같아야하므로 돌아가면서 혹시나 여는 괄호가 더 많은지 확인하여 체크해준다.
if(isRight) {
return input.substring(0, checkPoint) + solve(input.substring(checkPoint));
}
3-1. 만약 u가 올바른 괄호라면 v에 대해 위 과정을 반복하여 붙여주었다.
String result = "(" + solve(input.substring(checkPoint)) + ")";
4-1, 4-2, 4-3을 수행한 결과이다. 4-1은 여는괄호를 4-2는 v에 대한 실행을 4-3은 닫는 괄호를 붙여주도록 한다.
String u = input.substring(1,checkPoint-1);
String reverseU = "";
for(int i = 0; i < u.length(); i ++){
if(u.charAt(i) == '(')
reverseU = reverseU + ")";
else
reverseU = reverseU + "(";
}
return result + reverseU;
4-4, 4-5 u의 양 끝 값을 지워주고, u의 괄호를 각각 뒤집어줍니다. 그리고 뒤집어준 괄호를 위에서 생성한 괄호에 붙여서 return해주어 문제를 해결하였습니다.
구현코드
import java.util.Stack;
public class Solution {
public String solution(String p) {
return solve(p);
}
public String solve(String input){
if(input.length() == 0)
return "";
int checkPoint = 0;
int find = 0;
Stack<Character> stack = new Stack<>();
do{
stack.add(input.charAt(checkPoint));
if(input.charAt(checkPoint++) == '(')
find++;
else
find--;
}while (find != 0);
int closeCount = 0;
boolean isRight = true;
while (!stack.isEmpty()){
char p = stack.pop();
if(p == ')')
closeCount ++;
else
closeCount --;
if(closeCount < 0){
isRight = false;
break;
}
}
if(isRight) {
return input.substring(0, checkPoint) + solve(input.substring(checkPoint));
}
String result = "(" + solve(input.substring(checkPoint)) + ")";
String u = input.substring(1,checkPoint-1);
String reverseU = "";
for(int i = 0; i < u.length(); i ++){
if(u.charAt(i) == '(')
reverseU = reverseU + ")";
else
reverseU = reverseU + "(";
}
return result + reverseU;
}
}
잘못된 지식이나 궁금한 내용이 있을 경우 편하게 댓글 남겨주시면 감사하겠습니다 :)
'CodingTest > Programmers' 카테고리의 다른 글
[PGM_81302] 거리두기 확인하기 (java) (0) | 2022.02.09 |
---|---|
[PGM_17677] 뉴스 클러스터링 (java) (0) | 2022.02.08 |
[PGM_72411] 메뉴 리뉴얼 (java) (0) | 2022.02.04 |
[PGM_77485] 행렬 테두리 회전하기 (java) (0) | 2022.02.01 |
[PGM_12973] 짝지어 제거하기 (java) (0) | 2022.01.31 |