Kotlin/Algorithm Problems

<프로그래머스> 괄호 변환(Lv.2)

re트 2023. 12. 26. 11:07
728x90

[깃허브]

https://github.com/heesoo-park/ForCodeKata/tree/main/%EA%B4%84%ED%98%B8%20%EB%B3%80%ED%99%98

[프로그래머스]

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

 

문제를 이해하는데 시간이 오래 걸렸지 코드를 작성하는 건 그렇게 오래 걸리지 않은 문제였다.

기본적으로 문제 지문이 아주 세세해서 그대로 따라만 가도 풀렸다.

물론 내가 재귀를 잘 다루지 못 했다면 그냥 벽에 부딪혔겠지만 다행히 여러번 풀어왔었기에 잘 통과했다.

이 문제도 카카오에서 낸 문제였는데 거의 30분 정도만에 풀었던 거 같다.

 

보통 지금까지 풀었던 괄호문제는 올바른 괄호인지 아닌지까지만 갔는데 이 문제는 그걸 수정해주기까지 해야했다.

아마 흐름을 문제에서 알려주지 않았다면 더 높은 레벨의 문제가 되지 않았을까 싶다.

그래서 알고리즘의 흐름은 문제를 보면 다 알 수 있다.

 

내가 이 문제를 풀면서 느낀 것들은 오랜만에 재귀함수에서 반환값을 주었었다는 것이고 확실히 문자 추가, 수정이 많은 문자열에서는 StringBuilder가 훨씬 낫다는 것이었다.

재귀함수를 쓸 때 반환값을 주면 바로 전 단계로 반환값을 보내니까 원하지 않던 방향으로 가는 경우가 많아 전역변수에다가 값을 처리하는경우가 많았는데 이번 문제는 흐름이 명확하다보니 원하는 방향으로 잘 보낼 수 있었다.

 

지나고나서 생각해보면 뭔가 어려운 부분이 없었던 거 같다.

그냥 슥슥 작성하고 디버깅하고 제출하니까 통과했다.

 

해당 방법으로 작성한 코드는 다음과 같다.

import java.util.Stack

class Solution {
    fun solution(p: String): String {
        return if (checkCorrect(p)) p else solve(p)
    }

    // 재귀함수
    fun solve(w: String): String {
        if (w == "") return ""
        
        // StringBuilder 사용
        val u = StringBuilder()
        val v = StringBuilder()
        var isFull = false
        val count = arrayOf(0, 0)
        w.forEach {
            if (!isFull) u.append(it)
            else v.append(it)

            if (it == '(') count[0]++
            else if (it == ')') count[1]++

            if (count[0] == count[1]) isFull = true
        }

        return if (checkCorrect(u.toString())) {
            u.toString() + solve(v.toString())
        } else {
            u.deleteCharAt(0)
            u.deleteCharAt(u.lastIndex)
            u.forEachIndexed { index, it ->
                if (it == '(') u.replace(index, index + 1, ")")
                else if (it == ')') u.replace(index, index + 1, "(")
            }

            "(" + solve(v.toString()) + ")" + u.toString()
        }
    }

    // 올바른 괄호 문자열인지 판별하는 함수
    private fun checkCorrect(s: String): Boolean {
        val stack = Stack<Char>()

        s.forEach {
            if (it == '(') {
                stack.push(it)
            }
            else {
                if (stack.isNotEmpty()) stack.pop()
            }
        }

        return stack.isEmpty()
    }
}
반응형