ㅅㅇ

(프로그래머스) 주식가격 _ python 본문

SW_STUDY/알고리즘

(프로그래머스) 주식가격 _ python

SO__OS 2022. 6. 1. 19:15

문제

초 단위로 기록된 주식가격이 담긴 배열 prices가 매개변수로 주어질 때,

가격이 떨어지지 않은 기간은 몇 초인지를 return 하도록 solution 함수를 완성하세요.

제안 사항

  • prices의 각 가격은 1 이상 10,000 이하인 자연수입니다.
  • prices의 길이는 2 이상 100,000 이하입니다.

입출력 예

prices                                                                                          return

[1, 2, 3, 2, 3] [4, 3, 1, 1, 0]
  • 1초 시점의 ₩1은 끝까지 가격이 떨어지지 않았습니다.
  • 2초 시점의 ₩2은 끝까지 가격이 떨어지지 않았습니다.
  • 3초 시점의 ₩3은 1초뒤에 가격이 떨어집니다. 따라서 1초간 가격이 떨어지지 않은 것으로 봅니다.
  • 4초 시점의 ₩2은 1초간 가격이 떨어지지 않았습니다.
  • 5초 시점의 ₩3은 0초간 가격이 떨어지지 않았습니다.

 

문제풀이 (문제에 대한 해석 접근법)

이 문제는 코드 작성보다 문제 해석 자체를 이해하는 것이 어려웠다.

테스트케이스를 만들어 문제에 적용하면서 최대한 이해해보려고 했다.

 

문제에 대한 해석

- 테스트케이스 [1,2,3,2,1,1] 배열의 길이는 6.   6초동안의 주식 기록을 담았다.

  - > 즉, 배열 리스트의 길이는 주식 기록의 초를 의미한다. 

 

- 현재 인덱스 초 시점의 주가보다 떨어진 주가가 될 때까지 얼마의 기간인 걸렸는지 연산해 반환하는 것이다.

 

(1) 1초 시점의 주가는 1이다. 그리고 1보다 떨어진 주가는 없다.

6초동안의 측정이므로, 1초 시점부터 6초까지 5초 유지한다고 말할 수 있다.

[4]

 

(2) 2초 시점의 주가는 2이다. 그리고 현재주가 2보다 떨어진 주가는 5초가 된 시점이다.

6초동안의 측정 중에, 2초 시점부터 5초까지 3초 유지한다고 말할 수 있다. 

[4,3]

 

(3) 3초 시점의 주가는 3이다. 그리고 현재 주가 3 보다 떨어진 주가는 4초가 됐을 때이다.

6초동안의 측정 중에 3초 시점부터 4초까지 1초 유지한다고 말할 수 있다. 

그렇다면, 현재 인덱스 초 시점의 주가(3) 보다 떨어진 주가(2) 가 될 때까지 1초가 걸렸다. 

[4,3,1]

 

(4) 4초 시점의 주가는 2이다. 그리고 현재 주가보다 떨어진 주가는 없다.

5초동안의 측정이므로, 4초 시점부터 5초까지 1초 유지한다고 말할 수 있다.

[4,3,1,1]

 

(5) 5초 시점의 주가는 3이다. 5초 이후엔 데이터가 없기에 0초간 유지된다고 말할 수 있다.

[4,3,1,1,0]

 

접근법

- prices 배열에서 현재 주가를 기준으로 떨어진 주가가 어느 시점 인덱스인지 알아야 한다.

 

- 현재 주가 [i] 에서 앞으로의 주가들과 [i+1:] 비교해나가야 한다. 주가가 떨어졌는지 / 올랐거나 유지중인지

올랐거나 유지중이라면 1초가 지났다는 의미로 count +1 를 하고 다음 인덱스 값과 비교한다. 

떨어졌다면 1초가 지났다는 의미로 count+1를 하고 이 시점(떨어진)까지의 기간을 기록하는 것이므로 

비교를 멈추고(break) count한 이 값을 기록한다.

만약, 현 주가보다 작은 값이 없다면 6초까지의 시간 마지막 초 인덱스까지 count될 것이다.

이렇게 연산하면, 현재 주가에서 떨어진 주가까지 기간을 잴 수 있을 것이다.

 

- 본 문제는 스택/큐로 주어졌다.

리스트에서 queue구현을 위해 pop(0)을 쓴다. 그러나, 이는 pop()에 비해 O(N)으로 시간이 오래 걸린다.

그리하여, 스택과 큐를 합친 deque 자료 구조를 사용한다.

사용함수 및 적용

1. deque 사용

deque :  스택과 큐를 합친 자료구조

 

De = deque()  # deque 생성De = deque(list)  # list를 deque화 한다.De.popleft()  # 가장 왼쪽에 있는 원소를 제거하고 그 값을 리턴

 

 

소스코드

from collections import deque

def solution(prices):
    answer = []
    prices = deque(prices) # prices 원소가 있는 큐 만든다.
    while prices: # pop으로 [] 빈 큐일 때 false 빈큐가 될 때까지.
        c = prices.popleft() # 첫번째 원소 빼낸다.
        cnt = 0
        for i in prices:
            cnt += 1
            if c > i: # 빼낸 후의 큐 원소들과 하나하나 비교.
                break # 떨어진 주가 시점에서 중단.

        answer.append(cnt)

    return answer

** n + (n-1) + (n-2) + (n-3) + ... + 1 번   n(n-1)/2,   ===>  O(n^2)

 

2. list, range() 함수로

- 처음에는 enumerate()를 사용하려고 했으나,

이는 반복 자료형 내 원소를 하나씩 다 봐야하니까 O(n) 인 반면, range()는 O(1)이기에 효율성이 떨어졌기에

range()를 사용하여야 했다.

 

소스코드

# 주가가격 문제

def solution(prices):
    answer = []
    le = len(prices)
    for i in range(le):
        cnt = 0
        for j in range(i+1,le):
            cnt+=1 # 1초씩 지났다는 의미
            if prices[i]>prices[j]: # 떨어졌는지 비교
                break
        answer.append(cnt)       
    return answer
    
solution([1, 2, 3, 2, 3, 2, 1,0, 1]) # 테스트 케이스

**  O(N^2)

 

정리 

- 주식가격의 떨어짐을 비교하기 위해서는 현재 시점 이후의 원소들과 계속 비교하여야 하는데 O(N) 인 방법이 있을까나.

- Stack 으로 작성하다가 에러로 일단 포기하였는데 다른 사람 풀이에서 스택을 이용한 풀이법이 있었다. 

  다음에 한 번 더 혼자 해보고 안 되면 풀이 참고해서 시도해봐야 겠다.

 

'SW_STUDY > 알고리즘' 카테고리의 다른 글

(백준) 팩토리얼 진법  (0) 2022.06.28
(프로그래머스) 비밀지도  (0) 2022.06.28
진법 변환/비트 연산  (0) 2022.06.24
(프로그래머스) 기능 개발 _ python  (0) 2022.06.09
알고리즘 이론 : 스택/큐  (0) 2022.05.31