12. Stock Prices

효율적인 시간복잡도를 고려한 문제해결방법(feat. 스택)

algorithm test

12. Stock prices

Sunhyup Lee. (2024). To be a successful candidate for the coding test. goldenrabbit. p.165.

Problem solving

1. 스택을 이용한 접근법

function solution(prices) {
  const n = prices.length;                // ① 주가 배열의 길이 저장
  const answer = new Array(n).fill(0);    // ② 결과 배열을 0으로 초기화

  const stack = [];                       // ③ 주가의 인덱스를 저장할 스택
  for (let i = 0; i < n; i++) {           // ④ 모든 주가를 순회하는 반복문
    while (stack.length > 0 && prices[i] < prices[stack[stack.length - 1]]) { 
      																		// ⑤ 현재 주가가 이전 주가보다 작으면
      const j = stack.pop();              // ⑥ 스택에서 주가 인덱스를 꺼냄
      answer[j] = i - j;                  // ⑦ 주가가 얼마나 유지되었는지 계산
    }
    stack.push(i);                        // ⑧ 현재 인덱스를 스택에 저장
  }
  while (stack.length > 0) {              // ⑨ 남아 있는 인덱스는 끝까지 주가가 유지된 경우
    const j = stack.pop();                // ⑩ 스택에서 인덱스를 꺼내어
    answer[j] = n - 1 - j;                // ⑪ 마지막까지 유지된 시간을 계산
  }

  return answer;                          // ⑫ 최종적으로 유지 시간을 반환
}

const n = prices.length;

  • nprices 배열의 길이입니다. 즉, 주가가 몇 초 동안 기록되었는지를 의미합니다. 이 값을 통해 전체 주가 데이터를 순회할 준비를 합니다.


const answer = new Array(n).fill(0);

  • answer는 결과를 저장할 배열입니다. 각 주가가 유지된 시간을 기록할 공간을 만들고, 초기값은 모두 0으로 채웁니다.
  • 이 배열의 인덱스는 주가가 기록된 시점과 일치하며, 각 시점에서 주가가 몇 초 동안 유지되었는지를 저장할 것입니다.


const stack = [];

  • stack은 주가가 떨어지지 않은 시점의 인덱스를 저장하는 배열입니다. 즉, 주가가 하락하지 않은 시점(초)을 기록하는 역할을 합니다.
  • 스택은 인덱스 값만을 저장하며, 나중에 해당 인덱스에서 주가가 얼마나 유지되었는지 계산할 때 사용됩니다.


for (let i = 0; i < n; i++) {

  • for 루프는 배열 prices를 처음부터 끝까지 한 번 순회하면서, 각 주가가 얼마나 유지되었는지를 계산합니다.
  • i는 현재 시점을 나타내는 인덱스입니다.


while (stack.length > 0 && prices[i] < prices[stack[stack.length - 1]]) {

  • while 문은 스택에 값이 있고, 현재 주가(prices[i])가 스택에 있는 마지막 인덱스의 주가(prices[stack[stack.length - 1]])보다 작을 때 실행됩니다.
  • 즉, 현재 시점의 주가가 이전 시점의 주가보다 낮아졌을 때 그 이전의 주가들이 더 이상 유지되지 않았다는 것을 의미합니다.


const j = stack.pop();

  • 스택에서 가장 최근에 저장된 주가의 인덱스를 꺼냅니다. 이 인덱스 j는 이전 주가가 떨어지지 않던 시점(초)를 의미합니다.


answer[j] = i - j;

  • 현재 주가 prices[i]가 더 낮아졌으므로, 스택에서 꺼낸 인덱스 j에 해당하는 주가는 현재 시점 i에서 주가가 떨어졌음을 의미합니다.
  • i - jj번 주가가 몇 초 동안 유지되었는지를 계산합니다. 이 값을 answer[j]에 저장합니다.


stack.push(i);

  • 현재 인덱스 i를 스택에 추가합니다. 이는 현재 주가가 이후 시점에서 얼마나 유지될지를 나중에 계산하기 위해 추가하는 것입니다.


while (stack.length > 0) {

  • 배열 prices의 순회를 다 마쳤을 때, 스택에 남아 있는 인덱스는 끝까지 주가가 떨어지지 않은 경우입니다.
  • 따라서 스택에 남아 있는 주가 인덱스들을 처리해줍니다.


const j = stack.pop();

  • 스택에서 인덱스를 하나씩 꺼냅니다. 이 인덱스 j는 끝까지 가격이 떨어지지 않은 주가의 시점을 의미합니다.


answer[j] = n - 1 - j;

  • n - 1마지막 시점(즉, 주가 배열의 끝)을 나타냅니다.

  • n - 1 - jj번 주가가 끝까지 유지된 시간을 의미합니다.

    예를 들어, 마지막 주가가 떨어지지 않았다면 answer[j]에 이 값을 저장합니다.


return answer;

  • 최종적으로 각 시점에서 주가가 유지된 시간을 담고 있는 answer 배열을 반환합니다.