Algorithm
function solution(s) {
let count = 0
for(let i=0; i<=s.length-1;i++) {
let stack = []
let str = ""
str += s.slice(i)
if(i>0) str += s.slice(0,i)
stack.push(str[0])
for(let j=1; j<=str.length-1;j++){
stack.push(str[j])
if(str[j]===")"){
if(stack[stack.length-2]!=="(") break;
else {
stack.pop()
stack.pop()
}
}
if(str[j]==="}"){
if(stack[stack.length-2]!=="{") break;
else {
stack.pop()
stack.pop()
}
}
if(str[j]==="]"){
if(stack[stack.length-2]!=="[") break;
else {
stack.pop()
stack.pop()
}
}
}
if(stack.length===0) {
count++
}
}
return count;
}
조금 지저분한 코드 같긴 하면서도 이해가 되긴 되는데 깔끔한 코드로 좀 더 활용하는 방법을 써야할 것 같다. 객체를 활용했으면 더 좋을 코드일 듯하다
stack
과 회전한 문자열을 둘 str
을 선언하고 회전한 문자열을 구하는 건 slice
를 사용한다.stack
에 미리 첫번째 괄호를 집어 넣은뒤 반복문을 돌려 닫히는 괄호가 나온지 확인한다.pop()
을 2번 발생시켜 한쌍의 괄호를 제거한다stack
의 원소가 존재하지 않기 때문에 length
가 0일때 count
를 올려준다function solution(s) {
if(s.length % 2 === 1) return 0;
let answer = 0;
const mapping = { "}" : "{", "]" : "[", ")" : "("};
for(let i = 0; i < s.length; i++) {
const stack = [];
const rotate = s.slice(i) + s.slice(0, i);
let flag = true;
for(let j = 0; j < s.length; j++) {
if(rotate[j] === "[" || rotate[j] === "(" || rotate[j] === "{" )
stack.push(rotate[j]);
else {
const last = stack.pop();
if(last !== mapping[rotate[j]]) {
flag = false
break;
}
}
}
if(flag) answer++;
}
return answer;
}
slice
로 문자열을 구한뒤에 반복문을 실행push
만 하고 닫힌 괄호일때 pop()
으로 마지막 stack
괄호를 빼고 만약 괄호가 매핑한 괄호와 맞지 않다면 false
처리 한 뒤 break
한다 flag
가 true
면 답을 1 증가시킨다CS
여러번 다루는 것 같은데 그만큼 자주 쓰이는 내용이긴 하다
js는 동기적인 언어지만 서버 데이터 요청하는 등 대기시간이 긴 작업의 경우 비동기 작업을 하기 때문
function printAnimals() {
const animals = getAnimals(); //응답시간이 길경우
console.log(animals); //먼저 실행
}
printAnimals(); // undefined
이런 문제가 생기기 때문에 비동기 처리 방식을 사용한다.
다만 Promise
와 async await
의 용도는 똑같지만 다른 점이 분명 있다
async
는 Promise
에 비해 간결하다. 거의 비슷하긴 하지만 들여쓰기도 라인 차지도 훨씬 적다async
는 에러 핸들링에 유리하다. Promise
의 then
을 사용하면 내부에 추가적인 catch
문을 적어야 하면 try-catch
와 함께할 때 catch
문이 중복되느 경우도 있다.async
를 사용할 경우 하나의 catch
만 해주면 된다async
는 에러 위치를 찾기 쉽다! 연속으로 호출 할때 Promise
는 then
으로 여러번 중복되다 보니 찾기가 어려울 수 잇는데 async await
은 에러 위치를 쉽게 특정할 수 있다async function sample() {
const data1 = await sampleFunc(); // 문제 발생시 data1값이 유효치 않음
const data2 = await sampleFunc2(data1);
return data2;
}
오늘 푼 알고리즘에 stack이 있었기에 한번 다뤄보고 가자
쌓아 올린다는 것을 의미하는데 책을 쌓는 것처럼 차곡차곡 쌓아 올린 형태의 자료구조
후입 선출(LIFO, Last-in-first-out)
특징
push
, top을 통한 삭제하는 연산 pop
활용 예시
후입 선출을 활용해서 여러 분야에서 활용 가능
줄을 서서 기다리는 것인데 선입 선출 방식(FIFO, First in first out)의 자료구조이다
특징
정해진 곳을 통해서 삽입, 삭제가 이루어지는 스택과는 달리 큐는 한쪽 끝에서 삽입, 다른 쪽 끝에서 삭제 작업이 양쪽으로 이루어진다.
이때 삭제 연산만 수행되는 곳을 프론트(front), 삽입 연산만 이루어지는 곳을 리어(rear)로 정하여 각각의 연산작업만 수행된다.
이때, 큐의 리어에서 이루어지는 삽입 연산을 인큐(enQueue) 프론트에서 이루어지는 삭제연산을 디큐(dnQueue)라고 부른다
즉, 뮤에는 프론트 원소는 가장 먼저 큐에 들어왔던 첫번재 원소가 되는 것이고 리어 원소는 가장 늦게 큐에 들어온 마지막 원소가 된다.
활용예시
큐는 주로 데이터가 입력된 시간 순서대로 처리해야 할 필요가 있는 상황에 이용
이때 javascript는 shift
를 사용하는데 시간 복잡도가 O(n)으로 사용시 주의해야 한다. 앞의 한칸을 제거하며 배열 요소들을 앞으로 한칸씩 이동시키다 보니 배열 길이에 비례하여 시간이 소요된다.
pop
과 push
는 O(1)의 시간복잡도를 가진다
서울오면 연락한다며 언제할건데~