[코딜리티] Brackets (JavaScript)

dosanahnchangho·2020년 9월 17일
0

문제 출처

문제 요약

  • N 개의 문자로 구성된 문자열 S가 주어짐
  • 문자열 S는 "(", "{", "[", "]", "}" 또는 ")"의 문자로만 구성됨
  • 괄호 식이 올바르면 1을, 아니면 0을 return
  • N은 [0..200,000] 범위 내의 정수
  • 가장 효율적인 알고리즘 작성

문제 풀이

1회 시도

function removeAll(str, c) {
  return str.split(c).join("");
}
function solution(S) {
  if (!S) {
    return 1;
  }

  const counts = {
    "(": 0,
    "{": 0,
    "[": 0,
    "]": 0,
    "}": 0,
    ")": 0,
  };

  S.split("").forEach((e) => {
    ++counts[e];
  });

  if (
    counts["("] !== counts[")"] ||
    counts["{"] !== counts["}"] ||
    counts["["] !== counts["]"]
  ) {
    return 0;
  }

  S = removeAll(S, "()");
  S = removeAll(S, "[]");
  S = removeAll(S, "{}");

  return S === "" ? 1 : 0;
}
  • 각 괄호의 개수를 구해서 짝이 안맞으면 0 리턴
  • 개수가 맞으면 괄호들을 지워나간다
  • 당연히 정답, 퍼포먼스 모두 실패

2회 시도

function removeAll(str, c) {
  return str.split(c).join("");
}

function removeNest(str) {
  if (
    str.indexOf("()") > -1 ||
    str.indexOf("[]") > -1 ||
    str.indexOf("{}") > -1
  ) {
    str = removeAll(str, "()");
    str = removeAll(str, "[]");
    str = removeAll(str, "{}");
    return removeNest(str);
  } else {
    return str;
  }
}

function solution(S) {
  return removeNest(S) == "" ? 1 : 0;
}
  • 1회차랑 같은 개념이지만 불필요한 개수 구하기 제거
  • 더이상 인접합 괄호가 없을때까지 제거해 나간다.
  • 정확도 맞지만 퍼포먼스가 떨어짐

3회 시도

function removeAll(str, c) {
  return str.split(c).join("");
}

function valid(str, start, end) {
  if (str.indexOf(end) < str.indexOf(start)) {
    throw 0;
  }
  if (str.lastIndexOf(end) < str.lastIndexOf(start)) {
    throw 0;
  }
}

function removeNest(str) {
  valid(str, "(", ")");
  valid(str, "[", "]");
  valid(str, "{", "}");
  if (
    str.indexOf("()") > -1 ||
    str.indexOf("[]") > -1 ||
    str.indexOf("{}") > -1
  ) {
    str = removeAll(str, "()");
    str = removeAll(str, "[]");
    str = removeAll(str, "{}");
    return removeNest(str);
  } else {
    return str;
  }
}

function solution(S) {
  try {
    return removeNest(S) == "" ? 1 : 0;
  } catch (e) {
    return e;
  }
}
  • 괄호를 제거해 나가는 과정 중에 여는 괄호 닫는 괄호의 위치로 검사하는 로직을 추가한다.
  • 조금이라도 루프 횟수가 줄지만 코딜리티 기준 2회 차랑 동일한 퍼포먼스 점수...

마지막

function lastValid(last, c) {
  if (last != c) {
    throw 0;
  }
}

export default function solution(S) {
  try {
    const stack = [];

    for (let i = 0; i < S.length; i++) {
      switch (S[i]) {
        case "(":
        case "{":
        case "[":
          stack.push(S[i]);
          break;
        case ")":
          lastValid(stack.pop(), "(");
          break;
        case "}":
          lastValid(stack.pop(), "{");
          break;
        case "]":
          lastValid(stack.pop(), "[");
          break;
      }
    }

    return stack.length > 0 ? 0 : 1;
  } catch (e) {
    return e;
  }
}
  • 결국 구글 신의 도움을 닫았다. 출처 블로그 : https://miiingo.tistory.com/328 (감사합니다 👍)
  • 여는 괄호를 스택에 쌓아 가다 닫는 괄호를 만나면 스택의 마지막 요소와 짝이 맞는지 검사하면 된다.
  • 코드를 간결하게 하기 위해 throw 와 try catch 로 처리 했다.

결론

  • 스택 개념을 응용하는 케이스들을 좀 머리속에 익숙하게 해야 되겠다.
profile
프론트 엔드 개발자

0개의 댓글