[프로그래머스 코딩테스트 연습문제] 괄호 회전하기 문제 풀이 with 자바스크립트(Javascript) & 자바(Java)

Re_Go·2024년 7월 5일
0

코딩테스트연습

목록 보기
94/106
post-thumbnail

1. 첫번째 문제 풀이(2024-07-05)

해당 문제는 일전에 풀었던 괄호 짝 맞추는 문제 를 풀어서인지 딱 봤을 때 스택 문제라는걸 알게 되었는데요. 달랐던건 이번에는 통일된 유형의 괄호가 아니라 괄호가 무려 3 종류라는 사실...!

그래도 그때 풀었던 감은 반 년이 지나도 아직 남아있었던 덕분인지 어떻게 풀어야 할지 정도는 알고 있었던지라 이번에도 '노가다'를 좀 했답니다 ㅎ... 스택 알고리즘은 그림으로 보여드리는게 쉬울 것 같아 그림을 첨부해 드리니 확인 부탁드려요!

  1. 짝이 맞는 경우

(자료 출처 : 아 미리캔버스로 만드는거 쥰내 힘드네...)

  1. 짝이 맞지 않는 경우 1 : 제 짝이 아닐 때 (두번째 그림 주황원 오타 ...)

  1. 짝이 맞지 않는 경우 2 : 닫는 짝이 먼저 나오고 스택에 제 짝이 없을 때 (닫는 짝이 먼저 나오면 제 짝이 없거나, 제 짝이 아니거나 둘 중 하나)

이번에도 그림을 이용하여 알고리즘을 설명해 보았는데요. 이렇게 설명을 드리니 제 입장에선 훨씬 깔끔해 보여서 나름 만족합니다 ㅎㅎ (워낙 글로 풀어쓰는걸 잘 못하는지라 😅) 물론 배열이 옆으로 이동한 뒤에 또 비교를 해야하기 때문에 이것 또한 처리를 따로 해주어야 합니다. (slice로 이용)

이에 대한 알고리즘을 글로 잠깐 풀어쓰자면, for문을 전달 받은 문자열 만큼 돌면서 새로운 배열을 하나 생성하는데, 밀림 효과를 줘야하기 때문에 매번 증가하는 i의 값을 이용해서 왼쪽으로 이동하는 효과를 줍니다.

예를 들어 s가 "123456" 라고 한다면

i가 0일때는 -> s.slice(0) + s.slice(0,0) (변화 x)
i가 1일때는 -> s.slice(1) + s.slice(0,1) = "23456"+"1" -> "234561"
i가 2일때는 -> s.slice(2) + s.slice(0,2) = "3456"+"12" -> "345612"
i가 3일때는 -> s.slice(3) + s.slice(0,3) = "456"+"123" -> "456123"
i가 4일때는 -> s.slice(4) + s.slice(0,4) = "56"+"1234" -> "561234"
i가 5일때는 -> s.slice(5) + s.slice(0,5) = "6"+"12345" -> "612345"

물론 문자열은 불변하는 값이라 원래는 손을 대지 못하는대요! 대신 slice는 원본을 변경하지 않으면서 특정 인덱스 만큼을 추출하는 메서드이기 때문에 문자열에도 slice를 사용 가능한 것이죠 ㅎㅎ

아무튼 아래는 그에 대한 JS 코드 풀이입니다!

  1. 자바스크립트 버전
// 전달 받은 배열의 요소들이 전부 짝에 맞는지 확인하는 함수
function rotateChecker(arr) {
    let stack = [];
    let count = 0;
  	// for-of 돌리고
    for (let char of arr) {
      	// 여는 괄호면 스택에 저장
        if (char === '{' || char === '[' || char === '(') {  // 여는 괄호인 경우
            stack.push(char);
        // 닫는 괄호일 때
        } else if (char === '}' || char === ']' || char === ')') {  // 스택 배열이 비어있는 경우, 즉 위의 그림 예시 3번에 해당 될 경우 false를 반환
            if (stack.length === 0) return false;
			// 조건문에 거치지 않았다면 그 다음 조건문으로 짝이 맞는지를 비교해서 맞으면 count 증가
            let last = stack.pop();
            if ((char === '}' && last === '{') ||
                (char === ']' && last === '[') ||
                (char === ')' && last === '(')) {
                count++;
            }
        }
    }
  	// for문이 끝난 후 배열의 길이에 2를 나눈 값이 count의 값과 같을 때, 얘를 들어 배열 길이가 6이고 이를 나눈 값이 3인데 count가 3이라면 제 짝을 모두 찾은 셈( ([{ 기호의 짝인 )]}를 더하면 배열의 길이만큼 되니 이를 2로 나눈 값은 곧 ([{의 짝을 모두 확인하여 그때마다 count를 누적 증가시킨 셈 )이므로 이 조건의 결과값을 반환
    return arr.length/2 === count;
}

function solution(s) {
    let count = 0;

    for (let i = 0; i < s.length; i++) {
        let arr = s.slice(i) + s.slice(0,i);
        if (rotateChecker(arr))count++;    
    }
    return count;
}

그리고 자바 버전으로 구현한 코드는 다음과 같습니다.

  1. 자바 버전
import java.util.Stack;

class Solution {
    public static int solution(String s) {
        int count = 0;

        for (int i = 0; i < s.length(); i++) {
            String arr = s.substring(i) + s.substring(0, i);
            if (rotateChecker(arr)) {
                count++;
            }
        }

        return count;
    }

    public static boolean rotateChecker(String arr) {
        Stack<Character> stack = new Stack<>();
        int count = 0;

        for (char c : arr.toCharArray()) {
            if (c == '{' || c == '[' || c == '(') {  // 여는 괄호인 경우
                stack.push(c);
            } else if (c == '}' || c == ']' || c == ')') {  
                if (stack.size() == 0) return false;

                char last = stack.pop();
                if ((c == '}' && last == '{') ||
                    (c == ']' && last == '[') ||
                    (c == ')' && last == '(')) {
                    count++;
                }
            }
        }

        return arr.length() / 2 == count;
    }
}

2. 자바와 자바스크립트 풀이 차이점

  1. JS는 배열 데이터를 다룰 때 shift, unshift, push, pop으로 쉽게 LIFO 구현할 수 있는 반면, 자바의 경우 List 컬렉션 중 Stack으로 push와 pop을 이용해 LIFO를 구현할 수 있는데요. 뿐만 아니라 LinkedList를 사용하면 push, pop과 비슷한 addfirst와 removelast 메서드도 추가적으로 사용 가능하다고 합니다. (근데 왜 JS가 더 친근하게 다가오지...?)

  2. JS에서는 배열이 비어있는지 확인하려면 length가 0인지를 보면 되는데, 자바에서는 isEmpty 메서드를 제공하더라고요? 또 왼쪽 이동 효과를 주기 위해 문자열을 추출하는 방법으로 JS는 slice를 사용한 반면, 자바는 substring을 사용하였다는 점도 차이점이라 할 수 있겠습니다. (그 외 자바의 별도 타입 지정도 차이점이라 할 수 있겠죠.)

profile
인생은 본인의 삶을 곱씹어보는 R과 타인의 삶을 배워 나아가는 L의 연속이다.

0개의 댓글