1. 문제 출처
백준 - 1912번: 연속합 문제로 이동하기
우선 링크로 가서 문제를 보도록 하자.
2. 문제 설명
문제
n개의 정수로 이루어진 임의의 수열이 주어진다. 우리는 이 중 연속된 몇 개의 수를 선택해서 구할 수 있는 합 중 가장 큰 합을 구하려고 한다. 단, 수는 한 개 이상 선택해야 한다.
예를 들어서 10, -4, 3, 1, 5, 6, -35, 12, 21, -1 이라는 수열이 주어졌다고 하자. 여기서 정답은 12+21인 33이 정답이 된다.
입력
첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.
테스트 케이스1
10
10 -4 3 1 5 6 -35 12 21 -1
정답: 33
테스트 케이스2
10
2 1 -4 3 4 -4 6 5 -5 1
정답: 14
3. 문제 풀이
(1) 논리의 구성 - 동적 계획법(DP)
이 문제의 핵심은 최대 계산 값을 계속 기록하면서, 최대한 빠른 시간 안에 해결하는 것입니다.
흔히 말하는 Memorization(기억법)이라고 하죠. 대표적인 DP 스킬 중에 하나인데요, 여기서 이게 어떻게 쓰이는지 한 번 보도록 하겠습니다.
1) 손코드의 계획
첫 번째. i번째 데이터 이전까지 합을 계산해 봤을 때 최대값을 지속적으로 기록한다.
- 원칙1. 이전까지의 합이, 그냥 i번째 숫자보다 작은 경우 이전의 기록들은 무의미하다.
그러니 그냥 i번째 숫자를 최대값으로 설정한다.
(2) 실제 구현코드
1
2
3
4
5
6
7
|
n = int(input())
m = list( map(int, input().split(' ')))
for i in range(1, n):
m[i] = max(m[i], m[i] + m[i-1])
print(max(m))
|
cs |
1) 코드의 설명
- 반복문의 시작을 1에서 하는 이유
: 문제 풀이의 핵심은 "이전까지 모든 숫자의 합 중 최대값"을 그때그때 기록하는 것입니다.
데이터의 시작점인 0번 인덱스는 이전까지의 합이 0 자신 자체이기 때문에 아무런 필요가 없는 것이죠.
그래서 반복문의 시작은 1부터 합니다.
- m[i] = max( m[ i ], m[ i ] + m[ i-1 ]) -> i번 째 데이터를 업데이트하는 이유
: i번째 인덱스는 핵심코드의 논리인 "이전까지 모든 숫자의 합 중 최대값"이기 때문에 수정을 해 주어야 합니다.
예를 들어서 10번째 인덱스를 계산할 차례인데, 9번째 인덱스까지의 모든 경우의 수를 다시 계산하면 시공간 복잡도가 낭비되는 단점이 있죠.
그래서 그냥 data의 9번째 값 자체를 이때까지 나온 모든 경우의 수 중에서 가장 최대값으로 업데이트를 하는 것입니다.
이 부분은 아래의 시뮬레이션을 보면 이해가 빠르실 거에요.
(3) 코드로 돌아가는 테스트 케이스 시뮬레이션
1) 기본 데이터 준비
n
m = [ 10, -4, 3, 1, 5, 6, -35, 12, 21, -1 ]
첫 번째 Loop. i = 1
m[1] = max( -4, -4+ 10 = 6 ) -> m[1] = 6
m = [ 10, 6, 3, 1, 5, 6, -35, 12, 21, -1 ]
이때 6은 이전까지 연속된 합 중 최대값을 기록한 것입니다. DP - Memorization
두 번째 Loop. i = 2
m[2] = max( 3, 3+6= 9) -> m[2] = 9
m = [ 10, 6, 9, 1, 5, 6, -35, 12, 21, -1 ]
9 또한 이전가지 연속된 합 중 최대값을 기록한 것입니다.DP - Memorization
이렇게 루프가 다 돌았을 때 나오는 데이터의 경우의 수는 아래와 같습니다.
m = [10, 6, 9, 10, 15, 21, -14, 12, 33, 32]
그래서 m 중에서 가장 큰 수는 33이기에 정답이 되는 것입니다.
이런 식으로 자신의 논리가 정확한지 확인하기 위해서는 손으로 하나하나 테스트 케이스를 적어가면서, 기본적인 프로그래밍 원리에 부합하는 확인하는 것도 좋은 방법이랍니다.
'Python > 코딩 테스트 해설집' 카테고리의 다른 글
백준 - 1439번 - 뒤집기 [파이썬] (0) | 2021.02.15 |
---|---|
프로그래머스 - 탐욕법(Greedy) - 체육복 [파이썬] (0) | 2021.02.06 |
프로그래머스 - 스택/큐 - 프린터[파이썬] (0) | 2021.02.02 |
프로그래머스 - 해쉬 - 전화번호 목록 (0) | 2021.01.17 |
프로그래머스 - 해쉬 - 완주하지 못 한 선수 (0) | 2021.01.14 |