반응형

오늘의 문제는 레벨 2에 해당하는 <방문 길이>인데요.
(문제 출처 : 프로그래머스 https://school.programmers.co.kr/learn/courses/30/lessons/76502)

프로그래머스는 블로그 게재 시 문제 여지가 있어
자세한 내용 없이 문제 제목과 링크로 대체합니다.

대괄호, 중괄호, 소괄호로 구성된 문자열이 주어질 때
이 문자열을 왼쪽으로 한 칸씩 옮기면서(회전하면서)
올바른 괄호 문자열이 만들어지는 횟수를 찾는 문제였다.

( ) { } [ ] , ( { } ) [ ] 와 같이
괄호들이 순서대로 잘 닫겨 있다면
올바른 괄호 문자열이다.

옮긴 칸수 문자열 올바른지 여부
0 ( ) { } [ ]
1 ) { } [ ] ( 아니오
2 { } [ ] ( )
3 } [ ] ( ) { 아니오
4 [ ] ( ) { }
5 ] ( ) { } [ 아니오

올바른지 여부에 "네"가 총 3개니까
결과값으로 3을 리턴하면 되는 형태

1) 문자열을 왼쪽으로 하나씩 미는 반복문이 필요하고

2) 문자열 내부를 돌면서 올바른지 여부를 확인하는 반복문도 필요했다
반복문 내부에는 스위치문과 스택을 활용해
2-1) 열린 괄호들이면 push하고
2-2) 닫힌 괄호들이면, 스택이 비지 않았다는 전제 하에
- pop한 열린 괄호가 지금 괄호와 짝인 경우에만
올바른 문자열인지 판단하는 r 값을 true로 바꿔주기로

1) 스택이 비어 있고 r 값이 true라면
올바른 문자열이니까 answer의 값을 하나 올려준다
1) 마지막으로 문자열을 왼쪽으로 미는 로직을 추가했다

코드로 보면 이런 느낌이에요.
중복도 있고 조금 더 예쁘게 짤 수 있을 것 같기는 한데
일단 풀었다에 의의를 두는 코드라죠^^

import java.util.*;

class Solution {
    public int solution(String s) {
        int answer = 0;
        String sc = s;
        int size = sc.length();
        
        for (int i=0; i<size; i++){ // 문자열을 왼쪽으로 미는 반복문
            // System.out.println("현재 문자열은 "+sc);
            
            boolean r = false;
            Stack<Character> stack = new Stack<>();
            
            // 문자열 내부를 검사하는 반복문
            for (int j=0; j<size; j++){
                char c = sc.charAt(j);
                switch (c){
                    case '(':
                        stack.push(c); break;
                    case '{':
                        stack.push(c); break;
                    case '[':
                        stack.push(c); break;
                    case ')':
                        if (stack.isEmpty() == false && stack.pop() == '(') {
                            r = true;}
                        else { r = false;} break;
                    case '}':
                        if (stack.isEmpty() == false && stack.pop() == '{') {
                            r = true; }
                        else { r = false; } break;
                    case ']':
                        if (stack.isEmpty() == false && stack.pop() == '[') {
                            r = true; }
                        else { r = false; } break;
                }
                // System.out.println(j + "번 자리에서 " + r);
            }
            if (stack.isEmpty() == true && r == true) {
                // 스택이 비어있고 true 라면 해당 회차는 올바름
                    answer++;
                // System.out.println(i+"칸 움직인 후에 " + answer);
            }
            if (1<size){
                String temp = sc.substring(1);
                char back = sc.charAt(0);
                sc = temp + String.valueOf(back);
            }
            }
        
        return answer;
    }
}

중간중간 결과물이 어떻게 나올지 궁금해서
온라인 컴파일러를 활용해 출력해봤다.
하다보니 스위치문에서 브레이크/컨티뉴가 헷갈렸거든요
(사실 아직도임 ㅋ)

내 의도대로 올바른 회차에만
answer 변수를 카운트하는 모습까지 확인된다.

정답 코드도 공부하자면

내가 스위치문으로 구성한 올바른 코드 확인 로직을 해쉬맵으로 구현했다.

HashMap<Character, Character> map = new = HashMap<>();
map.put(')', '(');

그리고 문자열을 왼쪽으로 미는 대신에
문자열 2개를 이어 붙이고
시작 인덱스를 하나씩 뒤로 보내는 방법을 택했다.
( ) { } [ ] ( ) { } [ ]

해시맵 안에 인덱스에 해당하는 모양이 없다면
열리는 괄호라는 의미라 스택에 집어 넣는다.

모양이 있고 스택이 비어 있지 않다면
스택에서 꺼낸 결과와 해시맵을 비교해서
짝이 맞지 않으면 다음 문자열을 확인하러 보낸다

위에서 중단하고 넘어가지 않았고
스택도 비어 있다면
올바른 괄호 문자열이다.

처음에는 막막했는데
책 기준 10번 문제 정도 오니까
시간이 조금 오래 걸리고
내 로직이 정답과는 많이 다르긴 해도
하나씩 풀 수는 있다
소소하게 작은 것부터 이뤄나가기👊

반응형

+ Recent posts