🕊 Link

Lv2. 괄호 변환 Javascript
https://programmers.co.kr/learn/courses/30/lessons/60058

🧑🏻‍💻 Code(javascript)

function checkCorrectArr(str) {
  if (str[0] === ")") return false;
  let leftCnt = 0;
  let rightCnt = 0;
  [...str].forEach((el) => {
    if (leftCnt >= rightCnt) {
      el === "(" ? leftCnt++ : rightCnt++;
    } else {
      return false;
    }
  });
  return true;
}

function solution(p) {
  if (!p) return "";
  let answer = "";
  let u = "";
  let v = "";
  let idx = 0;
  let uLeftCnt = 0;
  let uRightCnt = 0;
  for (let i = 0; i < p.length; i++) {
    p[i] === "(" ? uLeftCnt++ : uRightCnt++;
    idx++;
    if (uLeftCnt === uRightCnt) {
      u = p.slice(0, idx);
      v = p.slice(idx);
      break;
    }
  }
  if (checkCorrectArr(u)) {
    answer += u;
    answer += solution(v);
    return answer;
  } else {
    answer += "(";
    answer += solution(v);
    answer += ")";
    for (let i = 1; i < u.length - 1; i++) {
      u[i] === "(" ? (answer += ")") : (answer += "(");
    }
    return answer;
  }
}

💡 Solution

괄호 문자열의 종류

  • 균형잡힌 괄호 문자열 : 좌, 우 괄호의 숫자가 같을 경우,
  • 올바른 괄호 문자열 : 균형잡힌 괄호 문자열 중, 괄호의 순서까지 맞는 경우
// 올바른 괄호 문자열인지 확인하는 함수
function checkCorrectArr(str) {
  if (str[0] === ")") return false; // ")"로 시작하면 올바를 수가 없다.
  let leftCnt = 0;
  let rightCnt = 0;
  [...str].forEach((el) => { 
    // leftCnt가 rightCnt보다 크거나 같을 경우 로직을 돌면서 cnt++
    if (leftCnt >= rightCnt) {
      el === "(" ? leftCnt++ : rightCnt++;
    } else { // 예외 상황이면 올바르지 않은 괄호.
      return false;
    }
  });
  return true; // 예외 상황을 타지 않았으면 올바른 괄호.
}

function solution(p) {
  // 1. 입력이 빈 문자열인 경우, 빈 문자열을 반환합니다.
  if (!p) return "";
  let answer = "";
  // 2. 문자열 w를 두 "균형잡힌 괄호 문자열" u, v로 분리합니다.
  //    단, u는 "균형잡힌 괄호 문자열"로 더 이상 분리할 수 없어야 하며, v는 빈 문자열이 될 수 있습니다.
  let u = "";
  let v = "";
  let idx = 0;
  let uLeftCnt = 0;
  let uRightCnt = 0;
  // p를 돌면서 left와 right의 cnt를 올려주고, 
  // 두 값이 같아지는 순간, u와 v를 세팅하고 break
  for (let i = 0; i < p.length; i++) {
    p[i] === "(" ? uLeftCnt++ : uRightCnt++;
    idx++;
    if (uLeftCnt === uRightCnt) {
      u = p.slice(0, idx);
      v = p.slice(idx);
      break;
    }
  }
  if (checkCorrectArr(u)) {
    // 3. 문자열 u가 "올바른 괄호 문자열" 이라면 문자열 v에 대해 1단계부터 다시 수행합니다.
    // 3-1. 수행한 결과 문자열을 u에 이어 붙인 후 반환합니다.
    answer += u;
    answer += solution(v);
    return answer;
  } else {
    // 4. 문자열 u가 "올바른 괄호 문자열"이 아니라면 아래 과정을 수행합니다.
    //   4-1. 빈 문자열에 첫 번째 문자로 '('를 붙입니다.
    //   4-2. 문자열 v에 대해 1단계부터 재귀적으로 수행한 결과 문자열을 이어 붙입니다.
    //   4-3. ')'를 다시 붙입니다.
    //   4-4. u의 첫 번째와 마지막 문자를 제거하고, 나머지 문자열의 괄호 방향을 뒤집어서 뒤에 붙입니다.
    //   4-5. 생성된 문자열을 반환합니다.
    answer += "(";
    answer += solution(v);
    answer += ")";
    for (let i = 1; i < u.length - 1; i++) {
      u[i] === "(" ? (answer += ")") : (answer += "(");
    }
    return answer;
  }
}

👨🏻‍💻💭 Self Feedback

풀이 과정을 알려주는 친절한 문제였지만, 중간중간 실수가 많아서 오래걸렸던 문제.
예외 사항에 대한 고찰이 더 필요


  • 2021.04.27 - 최초 작성

댓글 환영 질문 환영
by.protect-me

profile
protect me from what i want

0개의 댓글