[프로그래머스/Level2] 괄호 변환 (JAVA)
📖 문제
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
💡 풀이 방식
• 구현, 재귀
문제에서 말한 순서대로 구현하면 된다..
1. 입력이 빈 문자열인 경우, 빈 문자열을 반환합니다.
2. 문자열 w를 두 "균형잡힌 괄호 문자열" u, v로 분리합니다. 단, u는 "균형잡힌 괄호 문자열"로 더 이상 분리할 수 없어야 하며, v는 빈 문자열이 될 수 있습니다.
→ int형 변수 open의 값을 통해 분리한다. 여는 괄호를 만나면 갯수+1, 닫는 괄호를 만나면 갯수 -1한다. 이 때 여는 괄호 수 = 닫는 괄호 수인 경우, "균형잡힌 괄호 문자열"이므로 현재 문자열을 u(균형잡힌 괄호 문자열)와 그 외 나머지 문자열 v로 분리한다.
StringBuilder u = new StringBuilder();
StringBuilder v = new StringBuilder();
int open = 0; // '(' 개수
for(int i = 0 ; i < w.length() ; i++) {
if(w.charAt(i) == '(') open++;
else open--;
if(open == 0) { // 균형잡힌 괄호 문자열인 경우, u와 v로 분리
u.append(w.substring(0, i + 1)); // 균형잡힌 괄호 문자열
v.append(w.substring(i + 1)); // 그 외 나머지 문자열
}
}
3. 문자열 u가 "올바른 괄호 문자열" 이라면 문자열 v에 대해 1단계부터 다시 수행합니다.
3-1. 수행한 결과 문자열을 u에 이어 붙인 후 반환합니다.
if(check(u.toString())) { // u가 올바른 괄호 문자열이라면
u.append(solve(v.toString()));
}
→ 올바른 괄호 문자열인지 판단하는 메서드
private static boolean check(String s) {
int cnt = 0;
for(char c : s.toCharArray()) {
if(c == '(') {
cnt++;
}
else {
cnt--;
if(cnt < 0) return false;
}
}
return true;
}
4. 문자열 u가 "올바른 괄호 문자열"이 아니라면 아래 과정을 수행합니다.
4-1. 빈 문자열에 첫 번째 문자로 '('를 붙입니다.
4-2. 문자열 v에 대해 1단계부터 재귀적으로 수행한 결과 문자열을 이어 붙입니다.
4-3. ')'를 다시 붙입니다.
4-4. u의 첫 번째와 마지막 문자를 제거하고, 나머지 문자열의 괄호 방향을 뒤집어서 뒤에 붙입니다.
4-5. 생성된 문자열을 반환합니다.
else {
StringBuilder tmp = new StringBuilder();
tmp.append("("); // 4-1
tmp.append(solve(v.toString())); // 4-2) v에 대해 재귀호출 수행한 후 붙이기
tmp.append(")"); // 4-3
tmp.append(reverse(u.toString())); // 4-4) u 조작해 붙이기
return tmp.toString(); // 4-5) 생성된 새 문자열 반환
}
→ 4-4단계 수행하는 메서드
private static String reverse(String str) {
StringBuilder s = new StringBuilder();
// 첫 번째랑 마지막 두 문자 제외하고 뒤집기
for(int i = 1 ; i < str.length() - 1 ; i++) {
s.append(str.charAt(i) == '(' ? ')' : '(');
}
return s.toString();
}
🔺 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
import java.util.*;
class Solution {
public String solution(String p) {
if(check(p))
return p;
return solve(p);
}
// 균형잡힌 괄호 문자열 -> 올바른 괄호 문자열 변환ㅁ ㅔ서드
private static String solve(String w) {
StringBuilder u = new StringBuilder();
StringBuilder v = new StringBuilder();
if(w.length() == 0) return "";
int open = 0; // '(' 개수
for(int i = 0 ; i < w.length() ; i++) {
if(w.charAt(i) == '(') open++;
else open--;
if(open == 0) { // 균형잡힌 괄호 문자열인 경우
u.append(w.substring(0, i + 1));
v.append(w.substring(i + 1));
if(check(u.toString())) { // u가 올바른 괄호 문자열이라면
u.append(solve(v.toString()));
}
else {
StringBuilder tmp = new StringBuilder();
tmp.append("(");
tmp.append(solve(v.toString())); // v에 대해 재귀호출 후 붙이기
tmp.append(")");
tmp.append(reverse(u.toString())); // u 조작해 붙이기
return tmp.toString(); // 새 문자열 반환
}
break;
}
}
return u.toString(); // u가 올바른 괄호 문자열인 경우에만 도달
}
// 올바른 괄호 문자열 판단 메서드
private static boolean check(String s) {
int cnt = 0;
for(char c : s.toCharArray()) {
if(c == '(') {
cnt++;
}
else {
cnt--;
if(cnt < 0) return false;
}
}
return true;
}
// 변환하는 메서드
private static String reverse(String str) {
StringBuilder s = new StringBuilder();
// 앞뒤 두 문자 제외하고 변환
for(int i = 1 ; i < str.length() - 1 ; i++) {
s.append(str.charAt(i) == '(' ? ')' : '(');
}
return s.toString();
}
}
|
cs |
💦 어려웠던 점
- 그냥 문제에서 말한 순서대로 그대로 구현하면 되는데 이걸 못 했다..... 구현력을 더 키워야 한다...ㅠ
- u가 앞쪽에 있는 경우, 뒤쪽에 있는 경우 이렇게 나눠서 진행하려고 했었는데 그게 아니고 그냥 문제에서 말한 그대로 구현하면 되는 것이었다,,,^^
🧐 새로 알게 된 내용
- 균형잡힌 괄호 문자열인지 확인할 때 스택을 써야하나 라는 생각을 했는데 그냥 변수 하나로만 더했다가 뺐다가 하면 더 간단하게 해결되는 문제였다,,
- 메서드 분리 안 해서 한꺼번에 작성하려 했더니 더 복잡하게 생각된 것 같다... 다음에는 로직에 맞는 메서드명 순서대로 적어놓고 그 다음에 필요한 메서드 구현하는 것으로!!
1회독 | 2회독 | 3회독 | 4회독 | 5회독 |
V |
(참고)
✔ 풀이 참고
[프로그래머스,Level 2] 괄호 변환 (JAVA 구현)
1. 입력이 빈 문자열인 경우, 빈 문자열을 반환합니다. 2. 문자열 w를 두 "균형 잡힌 괄호 문자열" u, v로 분리합니다. 단, u는 "균형 잡힌 괄호 문자열"로 더 이상 분리할 수 없어야 하며, v는 빈 문자
fbtmdwhd33.tistory.com