Algorithm

[CodeKata] 프로그래머스: 2.22(월), 멀쩡한 사각형

ttaeng_99 2021. 2. 22. 12:37
반응형

🥋 Ooooth!! (Level 2) : 멀쩡한 사각형

코드카타는 계속된다! 문제는 많은데 진도가 늦어 이번주부터는 토요일까지 주 6회로 풀려고 한다.

또한, 저번주에 풀이들이 길어지는 것을 느껴, 최대한 지양하고 싶었지만 우선 일단위로 포스팅하는 것으로 조정해보았다.

 

카카오답게 문제가 매우 길지만, 재귀함수를 통해 괄호쌍을 조정하여 '올바른 괄호 문자열' 로 가공하는 문제이다.

문제의 '용어의 정의' 부분에 로직이 설명되어 있어서, 이를 그대로 코드화하는 데 우선 집중했다.

 

🧮 풀이

function divider(str) {
  let compareCount = 1;
  for (let i = 1 ; i < str.length ; i++) {
    compareCount = str[i] === str[0] ? compareCount += 1 : compareCount-= 1;
    if (compareCount === 0) {
      return { u: str.slice(0, i+1), v: str.slice(i+1) }
    }
  }
}

function isPair(str) {
  let stack = [];
  for (let i = 0 ; i < str.length ; i++) {
    if (str[i] === '(') {
      stack.push(str[i])
    }
    else {
      stack.pop()
    }
  }
  return stack.join('') === '';
}

function solution(p) {
  if (p === '') {
      return '';
  }
  if (isPair(p)) {
    return p;
  }
  else {
    const { u, v } = divider(p);
    let answer;
    if (!isPair(u)) {
      answer = '(' + solution(v) + ')';
      for (i=1 ; i < u.length-1 ; i++) {
        answer += u[i] === '(' ? ')' : '(';
      }
    }
    else {
      answer = u + solution(v)
    }
    return answer
  }
}

1. 개별기능 함수 만들기

  • divider(): 괄호 문자열을 인자로 받아 u(균형잡힌 괄호 문자열), v(나머지) 로 잘라주는 함수, 비구조화를 위해 객체로 반환
  • isPair(): 괄호 문자열이 균형잡힌 괄호 문자열인지 검사하는 boolean 함수, 균형이 안맞다면 stack 에 '(' 남게됨

2. 괄호 문자열(p) '균형잡힌 괄호 문자열' 확인

  • p가 빈 문자열일 때 예외처리를 해준다. ('' 대신 p 반환해도 됨. isPair() 검사와 if로 묶어 p를 반환해도되나 직관성을 위해 분리)
  • isPair() 검사를 통해, p가 균형잡힌 괄호 문자열이라면 바로 반환하고 종료하면 된다.

3. 괄호 문자열(p) 분할 및 가공

  • 아니라면, divider() 를 통해 p를 u, v로 분리해준다.(비구조화) answer는 문제로직에 따라 가공될 새로운 괄호 문자열
  • u가 isPair() 거짓인 경우, '(' + v에 대한 재귀 + ')' 순으로 더한다. (solution(v)를 통해 solution() 함수를 재귀함수로 활용)
  • 이후, u의 양 끝을 제외한 나머지 괄호를 뒤집어서 더해야하므로, 1 ~ (length-1) 전까지 순회하며 위처럼 뒤집었다.
  • u가 isPair() 참인 경우, u와 v에 대한 재귀를 더한 값이 answer 가 된다.

 

🖇 리뷰

function solution(p){
  if(p === "")
    return p;
  
  let leftBrkNum = 0;
  let rightBrkNum = 0;
  let pIdx = 0;
  let result = '';
  let isRight = true;

  do{
    if(p[pIdx] === '(')
      leftBrkNum++;
    else
      rightBrkNum++;
    if(rightBrkNum > leftBrkNum)
      isRight = false;
    pIdx++;
  }while(leftBrkNum !== rightBrkNum)

  let u = p.substr(0, pIdx);
  let v = p.substr(pIdx);

  if(isRight){
    return u + solution(v);
  }
  else{
  u = u.substr(1,u.length-2).replace(/[\(]|[\)]/g, (a) => a === ')' ? '(' : ')');
  v = `(${solution(v)})`;
    return v + u;
  }
}

* 출처: taesung 님의 블로그 (taesung1993.tistory.com/m/28?category=868017 )

 

전반적인 풀이는 크게 다르지 않다.

균형잡힌 괄호 문자열을 확인하기 위해 위처럼 do - while 반복문을 사용하는 방법도 있다는 것을 알았다.

또한, 정규식 + replace() 조합을 통해 괄호 방향을 바꾼 것이 매우 좋은 방법이라고 생각한다.

 

 

좋은 풀이도 많이 있었지만, 나 역시 문제에 제시된 기능들을 각각 함수화하고 재귀를 활용해 푼 점이 매우 뿌듯하여 리뷰를 이정도로 마치겠다. 😃😃

반응형