-
연속 펄스 부분 수열의 합코딩 테스트/프로그래머스 2023. 10. 6. 17:03
문제
https://school.programmers.co.kr/learn/courses/30/lessons/161988
솔루션
- 펄스 수열은 [1,-1,1,-1] 또는 [-1,1,-1,1] 임.
- 특정 배열에 위의 펄스 수열 2가지를 각각의 원소에 곱해주면 둘은 부호만 반대 될 뿐 절대값은 같음
- 따라서 원래의 배열에 [1,-1,1,-1] 과 [-1,1,-1,1] 을 각각 곱한 뒤 두가지 배열을 추출하는 것이 아닌 [1,-1,1,-1]을 곱한 뒤 그것의 최댓값과 최솟값을 구한다. 최댓값과 최솟값은 [-1,1,-1,1]을 곱했을 때의 최솟값과 최댓값이므로 [1,-1,1,-1]을 곱한 뒤 나온 최댓값과 최솟값에 절대값을 구한 뒤 둘 중 더 큰 값이 정답이 됨.
- 그런데 부분 수열의 합을 구하기 위해 이중 반복문을 돌릴 경우 O(n^2)이 되므로 최대 길이가 500_000일 경우에는 시간 초과가 뜸.
- dp를 활용해서 합을 도출 (col 0은 최솟값, 1은 최댓값으로 생각)
- dp[i][0]은 i번째 원소를 마지막으로 포함할 때의 모든 연속 부분 수열중 최솟값 [i][1]은 최댒값
- dp[i][0] = min ( arr[i], arr[i]+dp[i-1][0] )
- dp[i][1] = max ( arr[i], arr[i]+dp[i-1][1] )
코드
from copy import deepcopy def solution(sequence): answer = 0 n = len(sequence) k = 1 for i in range(n): sequence[i] *= k k *= -1 dp = [[0, 0] for i in range(n)] dp[0] = [sequence[0], sequence[0]] min_val = 100_000_000 max_val = -100_000_000 for i in range(1, n): dp[i][0] = min(sequence[i], sequence[i]+dp[i-1][0]) dp[i][1] = max(sequence[i], sequence[i]+dp[i-1][1]) min_val = min(map(min, dp)) max_val = max(map(max, dp)) return max(abs(min_val), abs(max_val)) print(solution([2, 3, -6, 1, 3, -1, 2, 4]))
'코딩 테스트 > 프로그래머스' 카테고리의 다른 글
뒤에 있는 큰수 찾기 (자바스크립트) (1) 2024.04.25 셔틀버스 (파이썬) (1) 2023.10.09 [최단거리] 순위 (1) 2023.10.05 [DFS/BFS] 아이템 줍기 (파이썬) - 진행 중 (1) 2023.06.13 [카카오] 블록 이동하기 ( 파이썬 ) (0) 2023.06.10