백준_수열

임정민·2024년 1월 23일
0

알고리즘 문제풀이

목록 보기
149/173
post-thumbnail

백준 실버3 문제입니다. 실전에 대비하기 위해 60분 시간제한을 두고 풀었습니다.

문제

https://www.acmicpc.net/problem/2559

[나의 풀이1]

⌛ 15분 (일부 케이스 시간 초과)


N, K = map(int,input().split())
nums = list(map(int,input().split()))
length = len(nums) #10
end = K #2
max_hap = 0

while end<=length:
    
    start = end-K

    now_hap = sum(nums[start:end])

    if now_hap>max_hap:
        max_hap = now_hap
    end += 1

print(max_hap)

수열이 주어지고 연속된 K개의 합들 중 최대값을 구하는 문제입니다.

최초 구현 시 시작점(start)와 끝점(end)을 정의한 뒤 해당하는 구간을 슬라이싱하고 매번 합을 구하는 방식으로 표현하였지만 일부 케이스에서 시간 초과가 발생하여 다른 방식을 고안하였습니다.

[나의 풀이2]

⌛ 34분


N, K = map(int,input().split())
nums = list(map(int,input().split()))
length = len(nums) #10
end = K #2
start = end-K
max_hap = sum(nums[start:end])
stack = [(nums[0],max_hap)]

while end<length:
    
    front ,before_hap = stack.pop()
    now_hap = before_hap-front+nums[end]

    if now_hap>=max_hap:
        max_hap = now_hap
    start += 1
    stack.append((nums[start],now_hap))    
    end += 1

print(max_hap)

'나의 풀이1'에서 while 한번 실행 될때마다 start~end 구간에 대해 sum() 함수를 실행하여 시간이 오래걸리는 방식을 개선하기 위해 stack 구조에 (맨 앞 요소, 현재구간의 합)을 기억하는 알고리즘으로 구현하였습니다.

다음 구간의 합은 이전 구간의 맨 앞 요소 1개를 빼고 맨 뒤 요소 +1 인덱스 값을 더하면 되기 때문입니다.

[다른 사람의 풀이]

n, k = map(int, input().split())
array = list(map(int, input().split()))
psum = [0] * (n+1)
s = 0

for i in range(n):
    s += array[i]
    psum[i+1] = s

ans = -int(1e9)

for i in range(k, n+1):
    ans = max(ans, psum[i]-psum[i-k])
print(ans)

누적 합을 활용한 풀이입니다. 입력된 수열의 첫 인덱스부터 각 i번 까지의 누적 합을 차례대로 저장한 psum을 구한 뒤

i번째 누적합에서 i-k번째 누적합을 뺄셈하면 K간격의 연속된 수열의 합을 비교할 수 있었습니다.

감사합니다.

profile
https://github.com/min731

0개의 댓글