목표를 채운 날이 총 며칠인지와, 며칠 연속으로 채웠는지는 다른 질문이에요. 이번에는 기록이 중간에 끊기는 상황까지 생각하면서 가장 긴 연속 기록을 구해 볼게요.
이 글은 직접 만든 연습 문제예요. 코드업이나 프로그래머스의 문제 원문·테스트 데이터를 옮긴 글이 아니며, 해당 플랫폼의 채점 결과도 아닙니다.
날짜순으로 정리된 하루 공부 시간 minutes와 목표 시간 target이 주어져요. 목표 이상 공부한 날이 가장 길게 이어진 기간을 정수로 반환하면 됩니다.
공부 시간은 0 이상의 정수, 목표는 양의 정수라고 가정해요. 리스트의 원소 하나가 하루이며, 빠진 날짜는 없어요. 빈 리스트의 답은 0이에요.
minutes = [30, 45, 10, 60, 30, 40, 0]
target = 30
처음 이틀을 달성한 뒤 하루 목표를 못 채우고, 다시 사흘을 달성했어요. 따라서 답은 3이에요. 달성한 날의 총합인 5와 구분해야 해요.
def longest_streak(minutes, target):
current = 0
best = 0
for minute in minutes:
if minute >= target:
current += 1
best = max(best, current)
else:
current = 0
return best
current는 지금까지 이어지고 있는 기록이에요. 목표를 못 채운 날을 만나면 0으로 돌아가요.
반면 best는 이미 달성했던 가장 긴 기록이에요. 오늘 기록이 끊겨도 과거의 최고 기록까지 사라지면 안 되니 그대로 남겨 둡니다.
예제에서 두 변수는 다음처럼 바뀌어요.
| 공부 시간 | current | best |
|---|---|---|
| 30 | 1 | 1 |
| 45 | 2 | 2 |
| 10 | 0 | 2 |
| 60 | 1 | 2 |
| 30 | 2 | 2 |
| 40 | 3 | 3 |
| 0 | 0 | 3 |
마지막 날이 0분이어도 답은 3이에요. 그래서 마지막에 반환할 값은 current가 아니라 best예요.
assert longest_streak([], 30) == 0
assert longest_streak([10, 20], 30) == 0
assert longest_streak([30], 30) == 1
assert longest_streak([30, 40, 50], 30) == 3
assert longest_streak([30, 30, 0, 30], 30) == 2
assert longest_streak([30, 45, 10, 60, 30, 40, 0], 30) == 3
목표와 정확히 같은 날도 포함하므로 비교는 >=예요. 최고 기록을 달성할 때마다 갱신해서 마지막 날까지 계속 달성한 경우도 놓치지 않아요.
리스트를 한 번 읽으므로 시간 복잡도는 O(n), 추가 공간은 O(1)이에요. 원본 리스트는 바꾸지 않습니다.
비슷한 반복문이라도 무엇을 기억할지에 따라 결과가 달라져요. 이번 문제에서는 지금 이어지는 기록과 지금까지의 최고 기록을 나눠 두는 게 핵심이에요.