초 단위로 기록된 주식가격이 담긴 배열 prices가 매개변수로 주어질 때, 가격이 떨어지지 않은 기간은 몇 초인지를 return 하도록 solution 함수를 완성하세요.
prices의 각 가격은 1 이상 10,000 이하인 자연수입니다.
prices의 길이는 2 이상 100,000 이하입니다.
1초 시점의 ₩1은 끝까지 가격이 떨어지지 않았습니다.
2초 시점의 ₩2은 끝까지 가격이 떨어지지 않았습니다.
3초 시점의 ₩3은 1초뒤에 가격이 떨어집니다. 따라서 1초간 가격이 떨어지지 않은 것으로 봅니다.
4초 시점의 ₩2은 1초간 가격이 떨어지지 않았습니다.
5초 시점의 ₩3은 0초간 가격이 떨어지지 않았습니다.
function solution(prices) {
const n = prices.length;
const answer=new Array(n).fill(0);
const stack = [0];
for(let i=1; 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;
}
문제를 푸는 방식은 다음과 같다.
N^2인 복잡도를 이용하는 방식이 아닌 O(N)을 활용하기 때문에 배열의 모든 요소를 순차적으로 비교하는 것이 아니라 주식 가격이 처음으로 떨어지는 지점을 이용하여 다른 지점의 길이를 효율적으로 계산해야 한다.
이게 무슨 말이냐면 배열 [1, 5, 6, 3, 7]
이 있다고 가정하겠다
여기서는 가격이 계속 오르다가 6 -> 3으로 주식 가격이 처음 떨어지는데 이때 6의 길이는 1로 확정된다. 1초 동안 유지했다는 의미이고 answer 배열에 요소 6의 인덱스 번호인 answer[2]에 1을 저장하고 추가적으로 pop도 해줘야 하는데 왜냐면 길이가 확정됐기 때문에 필요가 없어진다.
그다음 5 > 3이므로 떨어졌다는 의미이고 3(요소 3의 인덱스) - 1(요소 5의 인덱스) 하여 길이는 2로 확정되고 answer 배열에 요소 5의 인덱스 번호인 answer[1]에 2를 저장하고 마찬가지로 pop을 실행한다. 2초 동안 유지했다는 의미이다.
이어서 1 < 3 이번에는 1초 주가의 가격은 떨어진 게 아니므로 pop을 하지 않고 3요소의 인덱스 3을 push 해준다. 마지막으로 7과 3을 비교하는데 가격이 떨어지지 않았으므로 7의 인덱스 4를 push 한다.
이렇게 되면 스택에 남는 요소들은 길이가 확정되지 않은, 가격이 끝까지 떨어지지 않은 주식이다.
이 요소들도 마지막에 pop 하면서 길이를 구해주면 된다.
이 부분은 코드의 마지막 while 문에 해당하는데 지금 stack = [0, 3, 4]이므로 pop 하면 4가 나올 것이고 j = 4 , answer[4] = 5 - 1- 4 => answer[4] = 0이 들어간다. 마지막 요소이므로 길이가 0인 게 맞다. 나머지도 대입해 보면 길이가 나올 것이다.
코드만 보면 길이가 짧기 때문에 엄청 간단해 보이지만 각 주가마다의 길이를 어떻게 확정하는지와 길이를 표현하기 위해 stack에는 index 값을 넣어주는 것, 가격이 떨어졌다는 것을 확인하는 조건문 마지막에 남은 stack 요소들의 길이를 구하는 것처럼 고려해야 할 부분들이 많았던 것 같다.