Skip to content

[jiyeeeah] 25.01.09#19

Merged
JooKangsan merged 19 commits intomainfrom
jiyeeeah
Jan 16, 2025
Merged

[jiyeeeah] 25.01.09#19
JooKangsan merged 19 commits intomainfrom
jiyeeeah

Conversation

@jiyeeeah
Copy link
Collaborator

@jiyeeeah jiyeeeah commented Jan 9, 2025

[스택]

  • 간단한 알고리즘에 대한 설명

스택의 ADT

ADT는 우리말로 추상 자료형 (Abstract Data Type)

추상 자료형 : 인터페이스만 있고 실제로 구현은 되지 않은 자료형 (일종의 자료형의 설계도)

연산 boolean isFull() 스택에 들어 있는 테이터 개수가 maxsize인지 확인해 boolean 값을 반환
boolean isEmpty() 스택에 들어 있는 테이터가 하나도 없는지 확인해 boolean 값을 반환
void push(ItemType item) 스택에 데이터를 푸시
ItemType pop() 스택에서 최근에 푸시한 테이터를 팝하고, 그 데이터를 반환
상태 Int top 스택에서 최근에 푸시한 데이터의 위치를 기록
ItemType data[maxsize] 스택의 데이터를 관리하는 배열. 최대 maxsize개의 데이터를 관리
  • data배열의 최대 크기는 maxsize ⇒ 인덱스의 범위는 0부터 maxsize-1
  • 아무 데이터도 없을 때 top-1
    • top0이면 데이터가 1개 있다는 것

스택의 세부 동작

  • push(3)
    1. isFull()을 우선 수행 ⇒ data 배열에 데이터가 가득 찼는지 확인
    2. 그렇지 않다면 top을 1만큼 증가시킨 후 (top = -1top = 0)
    3. top이 가리키는 위치 data[0]에 3을 추가
  • pop()
    1. isEmpty()를 우선 수행 ⇒ data 배열에 데이터가 없는건 아닌지 확인
    2. 데이터가 있다면 top을 1만큼 감소시키고
    3. 데이터 3을 반환

스택 구현하기

자바스크립트의 내장 메서드 사용

const stack = []; // 스택 초기화

// 스택에 데이터 추가
stack.push(1);
stack.push(2);
stack.push(3);

//스택에서 데이터 꺼냄
const topElement = stack.pop(); // 3
const nextElement = stack.pop(); // 2

const stackSize = stack.length;

📌 푼 문제

[기초]

[중급]

[심화]


📝 간단한 풀이 과정

문자열 뒤집기 / 기초

  • 이번 주차 주제인 stack을 의도적으로 사용하기 위해서 pop() 메서드를 사용했습니다.
function solution(my_string) {
  var answer = "";
  const str = my_string.split("");
  for (let i = 0; i < my_string.length; i++) {
    answer += str.pop();
  }
  return answer;
}

컨트롤 제트 / 기초

  • cmd가 Z인 경우는 pop하고, 아닌 경우는 push하여 stack에 남아있는 숫자들을 모두 더했습니다.
function solution(s) {
  const cmd = s.split(" ");
  const stack = [];
  for (const c of cmd) {
    if (c === "Z") {
      stack.pop();
    } else {
      stack.push(c);
    }
  }
  const answer = stack.reduce((acc, value) => acc + Number(value), 0);
  return answer;
}

문자열 계산하기 / 기초

  • my_stringsplit하여 배열로 변환했습니다.
  • stack에는 expression의 가장 첫번째 요소 (무조건 숫자임)를 넣어 초기화해줍니다.
  • expression+-가 나오면 stackpush합니다.
  • 그러다가 다시 숫자가 나오면 바로 전의 operator와 그 앞에 들어있는 숫자를 stack에서 꺼내어 더하기 또는 빼기를 수행합니다.
  • 계산한 값은 다시 stack에 넣어줍니다.
function solution(my_string) {
  const expression = my_string.split(" ");
  const stack = [Number(expression[0])];
  for (let i = 1; i < expression.length; i++) {
    if (expression[i] === "+" || expression[i] === "-") {
      stack.push(expression[i]);
    } else {
      const operator = stack.pop();
      const a = stack.pop();
      let result;
      if (operator === "+") result = a + Number(expression[i]);
      else result = a - Number(expression[i]);
      stack.push(result);
    }
  }
  return stack[0];
}

크레인 인형뽑기 게임 / 중급

  • moves를 돌면서 itemboard에서 하나씩 꺼내 stack에 담습니다.
  • stack에 이미 해당 item이 들어있다면 pop하고 answer2를 더합니다.
function solution(board, moves) {
  let answer = 0;
  const N = board.length;

  const stack = [];
  for (const move of moves) {
    for (let i = 0; i < N; i++) {
      if (board[i][move - 1] === 0) continue;

      const item = board[i][move - 1];
      if (stack.length > 0 && stack[stack.length - 1] === item) {
        stack.pop();
        answer += 2;
      } else {
        stack.push(item);
      }
      board[i][move - 1] = 0;
      break;
    }
  }
  return answer;
}

올바른 괄호 / 중급

  • 열린 괄호가 나오면 stack에 담습니다.
  • 닫힌 괄호가 나오면 stack이 비어있는지 확인합니다.
    • 비어있다면 false를 반환합니다.
    • 비어있지 않다면 pop()합니다.
function solution(s){
    const stack = [];
    for(const par of s) {
        if(par === "("){
            stack.push(par);
        }else {
            if(stack.length === 0) return false;
            else stack.pop();
        }
    }
    return stack.length === 0;
}

다트 게임 / 중급

  • dartResult를 돌면서 S, D, T, *, #, 숫자가 나오는 경우로 if 분기처리 했습니다.
  • stack에는 숫자만 남고, stack에 있는 숫자에 거듭제곱과 곱하기를 수행하여 마지막에 숫자들을 더합니다.
function solution(dartResult) {
  const stack = [];
  for (const c of dartResult) {
    const topIndex = stack.length - 1;
    if (c === "S") stack[topIndex] = stack[topIndex] ** 1;
    else if (c === "D") stack[topIndex] = stack[topIndex] ** 2;
    else if (c === "T") stack[topIndex] = stack[topIndex] ** 3;
    else if (c === "*") {
      stack[topIndex] *= 2;
      if (topIndex - 1 >= 0) stack[topIndex - 1] *= 2;
    } else if (c === "#") {
      stack[topIndex] *= -1;
    } else {
      if (c === "0" && stack[topIndex] === 1) {
        stack[topIndex] = 10;
      } else {
        stack.push(Number(c));
      }
    }
  }
  return stack.reduce((acc, val) => acc + val, 0);
}

괄호 회전하기

  • 이전에는 회전한 string을 따로 구해서 그 string들이 올바른 괄호인지 판단했습니다.
  • 책에서 회전을 다르게 구현했길래 복습하는 차원에서 다시 풀어봤습니다.
  • (i + j) % N 으로 회전하는 인덱스(?)를 구할 수 있더라구요.
  • 올바른 괄호 판단은 이전 문제와 동일합니다.
function solution(dartResult) {
  const stack = [];
  for (const c of dartResult) {
    const topIndex = stack.length - 1;
    if (c === "S") stack[topIndex] = stack[topIndex] ** 1;
    else if (c === "D") stack[topIndex] = stack[topIndex] ** 2;
    else if (c === "T") stack[topIndex] = stack[topIndex] ** 3;
    else if (c === "*") {
      stack[topIndex] *= 2;
      if (topIndex - 1 >= 0) stack[topIndex - 1] *= 2;
    } else if (c === "#") {
      stack[topIndex] *= -1;
    } else {
      if (c === "0" && stack[topIndex] === 1) {
        stack[topIndex] = 10;
      } else {
        stack.push(Number(c));
      }
    }
  }
  return stack.reduce((acc, val) => acc + val, 0);
}

주식 가격

  • stackindex를 저장했습니다. (개인적으로 이 부분이 헷갈리더라구요)
  • 마찬가지로, 책에서 한번 공부해 본 문제여서 복습하는 차원으로 다시 풀어봤습니다.
  • 원리는 일단 prices를 돌면서 price(의 index)를 stack에 담습니다.
  • price가 stack의 top에 있는 price보다 떨어지게 되면, 그 앞의 stack들을 돌면서 price보다 높은 경우의 시간(answer)을 확정합니다.
  • 전부 돌고 나면, stack에 남아있는 애들(끝까지 안 떨어진 애들)을 계산해줍니다.
function solution(prices) {
  const N = prices.length;
  const answer = new Array(N).fill(0);

  const stack = [0];
  for (let i = 1; i < N; i++) {
    for (let j = stack.length - 1; j >= 0; j--) {
      if (prices[stack[j]] > prices[i]) {
        answer[stack[j]] = i - stack[j];
        stack.pop();
      } else {
        break;
      }
    }
    stack.push(i);
  }
  const last = stack.pop();
  for (const s of stack) {
    answer[s] = last - s;
  }
  return answer;
}

택배 상자

  • 처음에 너무 복잡하게 풀다가 자꾸 6~10번 테케가 통과를 안하더라구요 ㅠㅠ
function solution(order) {
  let answer = 0;
  const tempConv = [];
  let boxIndex = 1;
  for (let i = 0; i < order.length; i++) {
    while (boxIndex <= order[i]) {
      tempConv.push(boxIndex++);
    }
    const top = tempConv[tempConv.length - 1];
    if (top !== order[i]) break;
    tempConv.pop();
    answer++;
  }
  return answer;
}
  • 틀린 답변입니다..
  • 너무 경우의 수를 많이 생각해서 if 문으로 나눠둔게 잘못이었던 것 같습니다.
  • 답변처럼 일단 temConv에 넣어두고 나서 top과 비교하면 되는 문제였던 것 같습니다.
// 틀린 답변
function solution(order) {
  const tempConv = [];
  const truck = [];
  for (let i = 0; i < order.length; i++) {
    const topTempConv = tempConv[tempConv.length - 1];
    if (tempConv.length > 0 && topTempConv === order[i]) {
      tempConv.pop();
      truck.push(order[i]);
    } else if (!tempConv.includes(order[i])) {
      const startNum = i - 1 >= 0 ? order[i - 1] + 1 : 1;
      for (let j = startNum; j < order[i]; j++) {
        tempConv.push(j);
      }
      truck.push(order[i]);
    } else if (tempConv.length === 0 && i + 1 === order[i]) {
      truck.push(order[i]);
    } else {
      return truck.length;
    }
  }
  return truck.length;
}

@tkddbs587
Copy link
Collaborator

코테 아직 왕초보인데 보면서 많이 배웠습니다 수고하셨어요!! 💪🏻

Copy link
Collaborator

@JooKangsan JooKangsan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다!! 해설 다 읽어봤는데 스택 주차이다 보니 스택에 관해서 의도적으로 사용한 부분들이 눈에 보였습니다!! 수고하셨어요!!

@JooKangsan JooKangsan merged commit d126819 into main Jan 16, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants