Stack & Queue

황지웅·2022년 3월 12일
0

Stack


1.stack이란?

  • 데이터(data)를 순서대로 쌓는 자료구조
  • LIFO(last In, First Out)
  • 스택은 아래의 두가지 연산을 가진 요소들의 집합인 추상 자료형
  • js에서는 배열의 push,pop,splice 등 을 이용해 구현할 수 있다.

2. stack을 이용해보았던 문제들

1.브라우저 뒤로 가기 앞으로 가기

조건

  • 새로운 페이지로 접속할 경우 prev 스택에 원래 있던 페이지를 넣고 next 스택을 비웁니다.
  • 뒤로 가기 버튼을 누를 경우 원래 있던 페이지를 next 스택에 넣고 prev 스택의 top에 있는 페이지로 이동한 뒤 prev 스택의 값을 pop 합니다.
  • 앞으로 가기 버튼을 누를 경우 원래 있던 페이지를 prev 스택에 넣고 next 스택의 top에 있는 페이지로 이동한 뒤 next 스택의 값을 pop 합니다.
  • 브라우저에서 뒤로 가기, 앞으로 가기 버튼이 비활성화일 경우(클릭이 되지 않을 경우)에는 스택에 push 하지 않습니다.

입력

  • 인자 1: actions
    String과 Number 타입을 요소로 갖는 브라우저에서 행동한 순서를 차례대로 나열한 배열
  • 인자 2: start
    String 타입의 시작 페이지를 나타내는 현재 접속해 있는 대문자 알파벳

출력

  • Array 타입을 리턴해야 합니다.

주의사항

  • 만약 start의 인자로 string 자료형이 아닌 다른 자료형이 들어온다면 false를 리턴합니다.
  • 새로운 페이지 접속은 알파벳 대문자로 표기합니다.
  • 뒤로 가기 버튼을 누른 행동은 -1로 표기합니다.
  • 앞으로 가기 버튼을 누른 행동은 1로 표기합니다.
  • 다음 방문할 페이지는 항상 현재 페이지와 다른 페이지로 접속합니다.
  • 방문한 페이지의 개수는 100개 이하입니다.
  • 반환되는 출력값 배열의 첫 번째 요소 prev 스택, 세 번째 요소 next 스택은 배열입니다. 스택을 사용자 정의한다면 출력에서는 배열로 변환해야 합니다.

입출력 예시

const actions = ["B", "C", -1, "D", "A", -1, 1, -1, -1];
const start = "A";
const output = browserStack(actions, start);

console.log(output); // [["A"], "B", ["A", "D"]]

const actions2 = ["B", -1, "B", "A", "C", -1, -1, "D", -1, 1, "E", -1, -1, 1];
const start2 = "A";
const output2 = browserStack(actions2, start2);

console.log(output2); // [["A", "B"], "D", ["E"]]

내 풀이

function browserStack(actions, start) {
  // TODO: 여기에 코드를 작성합니다.
  if(typeof start!=='string') return false
  let prev = []; //stack
  let next = [];//stack
  let nowPage = start;
  for (let i = 0; i < actions.length; i++) {
    if(prev.length===0&&actions[i]===-1){ //prev가 빈경우
      continue 
    }
    if(next.length===0&&actions[i]===1){//next가 빈경우
      continue
    }
    if(typeof actions[i]==='string'){//새로운 페이지인경우
      prev.push(nowPage);
      nowPage= actions[i]
      next =[];
    }
    if(actions[i]===-1){//뒤로가기인 경우
      next.push(nowPage);
      nowPage=prev.pop()
    }
    if(actions[i]===1){//앞으로가기인 경우
      prev.push(nowPage);
      nowPage =next.pop()
    }
  }
return [prev,nowPage,next]//제출
}

2.Queue


1.Queue란?

  • 자료구조 Queue는 Stack과 반대되는 개념으로
  • FIFO(First In First Out) 혹은 LILO(Last In Last Out) 을 특징으로 가지고 있다
  • js에서 배열의 unshift와 push,splice등 을 이용해 구현할 수 있다

2. Queue를 이용해보았던 문제들

1.박스포장

문제

  • 마트에서 장을 보고 박스를 포장하려고 합니다. 박스를 포장하는 데는 폭이 너무 좁습니다. 그렇기에 한 줄로 서 있어야 하고, 들어온 순서대로 한 명씩 나가야 합니다.
  • 불행 중 다행은, 인원에 맞게 포장할 수 있는 기구들이 놓여 있어, 모두가 포장을 할 수 있다는 것입니다. 짐이 많은 사람은 짐이 적은 사람보다 포장하는 시간이 길 수밖에 없습니다.
  • 뒷사람이 포장을 전부 끝냈어도 앞사람이 끝내지 못하면 기다려야 합니다. 앞사람이 포장을 끝내면, 포장을 마친 뒷사람들과 함께 한 번에 나가게 됩니다.
  • 만약, 앞사람의 박스는 5 개고, 뒷사람 1의 박스는 4 개, 뒷사람 2의 박스는 8 개라고 가정했을 때, 뒷사람 1이 제일 먼저 박스 포장을 끝내게 되어도 앞사람 1의 포장이 마칠 때까지 기다렸다가 같이 나가게 됩니다.
  • 이때, 통틀어 최대 몇 명이 한꺼번에 나가는지 알 수 있도록 함수를 구현해 주세요.

입력

  • 인자 1 : boxes
    • Number 타입을 요소로 갖는, 포장해야 하는 박스가 담긴 배열
      1 ≤ 사람 수 ≤ 10,000
      1 ≤ 박스 ≤ 10,000

출력

  • Number 타입을 리턴해야 합니다.

주의 사항

  • 먼저 포장을 전부 끝낸 사람이 있더라도, 앞사람이 포장을 끝내지 않았다면 나갈 수 없습니다.

예시

  • 만약 5, 1, 4, 6이라는 배열이 왔을 때, 5개의 박스를 포장하는 동안 1, 4 개의 박스는 포장을 끝내고 기다리게 되고, 6 개의 박스는 포장이 진행 중이기 때문에, 5, 1, 4 세 개가 같이 나가고, 6이 따로 나가게 됩니다. 그렇기에 최대 3 명이 같이 나가게 됩니다.
const boxes = [5, 1, 4, 6];
const output = paveBox(boxes);
console.log(output); // 3

const boxes2 = [1, 5, 7, 9];
const output2 = paveBox(boxes);
console.log(output2); // 1

나의 풀이

function paveBox(boxes) {
  //몇명이 나가는지 값들 저장하기
  let result =[]
  //몇명인지 세는 함수 만들기
   function howManypeople(boxes){
    let howManypeople = 0
    for(let el of boxes){
      if(boxes[0]>=el){
        howManypeople += 1
      }else{
        break
      }
    }
    return howManypeople
  }
  //박스의 선입 선출 조정
  for(;boxes.length>0;){
    result.push(howManypeople(boxes));
    boxes.splice(0,howManypeople(boxes));
  }
  // 최대값 리턴
  return Math.max(...result)
}

2.프린터

문제
프린터의 인쇄 작업 목록의 크기와 최대 용량을 가정하고 각기 다른 용량의 문서를 차례대로 인쇄하여 모든 문서가 인쇄되는데 최소 몇 초가 걸리는지 테스트하기로 했습니다.
린터의 제한사항인 인쇄 작업 목록의 크기 bufferSize, 최대 용량 capacities가 주어집니다. 인쇄할 문서의 크기가 나열된 배열 documents가 모두 인쇄되는데 걸리는 최소 시간을 반환하는 솔루션을 만들어 주세요.
입력

  • 인자1: bufferSize
    • Number 타입의 인쇄 작업 목록 크기
  • 인자 2: capacities
    • Number 타입의 인쇄 작업 목록에 추가될 수 있는 최대 용량
  • 인자 3: documents
    • Number 타입을 요소로 갖는 문서 크기가 나열된 배열
      출력
  • Number 타입을 리턴해야 합니다.
    제한사항
  • 인쇄 작업 목록은 칸으로 이루어져 있습니다.
  • 각 칸에는 한 개의 문서만 위치할 수 있습니다.
  • 문서는 1초에 한 칸만 이동할 수 있습니다.
  • 인쇄 작업 목록의 크기는 bufferSize이고 최대 용량 capacities 만큼 문서를 담을 수 있습니다.
    주의사항
  • bufferSize는 1 이상 100 이하입니다.
  • capacities는 100Kib 이하입니다.
  • 인쇄할 문서의 개수(배열의 길이) 1이상 100 이하입니다.
  • 문서 하나의 크기는 capacities를 초과하지 않습니다.
    1초가 지나면 인쇄 작업 목록에는 7Kib 크기의 문서가 추가됩니다.
    예시
  • 1초가 지나면 인쇄 작업 목록에는 7Kib 크기의 문서가 추가됩니다.
  • 2초일 때 인쇄 작업 목록의 최대 용량이 10Kib이기 때문에 4Kib 문서는 작업 목록에 들어갈 수 없습니다. 동시에 7Kib 문서는 작업 목록에서 1칸 앞으로 이동합니다.
  • 3초일 때 7Kib 문서는 인쇄 작업 목록에서 나와 프린터가 인쇄합니다. 동시에 4Kib 문서는 인쇄 작업 목록에 추가됩니다.
  • 4초일 때 4Kib 문서는 인쇄 작업 목록에서 1칸 앞으로 이동합니다. 동시에 5Kib 문서는 인쇄 작업 목록에 추가됩니다.
  • 5초일 때 4Kib 문서는 인쇄 작업 목록에서 나와 프린터가 인쇄합니다. 동시에 5Kib 문서는 인쇄 작업 목록에서 1칸 앞으로 이동합니다. 최대 용량 10Kib 제한으로 6Kib 문서는 인쇄 작업 목록으로 추가될 수 없습니다.
  • 6초일 때 5Kib 문서는 인쇄 작업 목록에서 나와 프린터가 인쇄합니다. 동시에 6Kib 문서가 인쇄 작업 목록에 추가됩니다.
  • 7초일 때 6Kib 문서는 인쇄 작업 목록에서 1칸 앞으로 이동합니다.
  • 8초일 때 6Kib 문서가 마지막으로 인쇄됩니다.
    입출력 예시
let bufferSize = 2;
let capacities = 10;
let documents = [7, 4, 5, 6];
let output = queuePrinter(bufferSize, capacities, documents);
console.log(output) // 8

나의 풀이

function queuePrinter(bufferSize, capacities, documents) {
  //업데이트변수
  let count = 0;
  //worklist (queue)
  const worklist = new Array(bufferSize).fill(null);
  //worklist에 null만있는지 확인하는함수
  function isallNull() {
    let allNull = true;
    for (let i = 0; i < worklist.length; i++) {
      if (worklist[i] !== null) { allNull = false }
    }
    return allNull
  }
  //재귀시킬함수
  function replay(capacities, documents) {
    //재귀종료조건
    if (isallNull() && documents.length === 0) return;
    //카운트 없데이트
    count += 1;
    //현재 worklist의 용량
    worklist.shift();
    let nowWorklistCapacities = worklist.reduce((pre, cur) => pre + cur,0);
    //작업수행
    if (nowWorklistCapacities + documents[0] <=capacities) {
      worklist.push(documents[0]); 
      return replay(capacities, documents.slice(1))
    } else {
      worklist.push(null);
      return replay(capacities, documents)
    }
  }
  replay(capacities, documents);//재귀함수 실행
  return count//업데이트된 카운트 제출
}

0개의 댓글