문제 설명
배열 nums와 값 k가 주어집니다. 이때 하위 배열(subarray) (i, j)의 점수는 다음과 같이 정의됩니다.
score(i, j) = min(nums[i..j]) × (j − i + 1)
여기서 "좋은(good) 하위 배열"은 시작 인덱스와 끝 인덱스 사이에 k가 포함되는, 즉 i <= k <= j를 만족하는 하위 배열을 뜻합니다. 목표는 좋은 하위 배열 중에서 얻을 수 있는 최대 점수를 구하는 것입니다.
예시
입력이 nums = [2,5,4,8,5,6], k = 3인 경우를 살펴보겠습니다. 최적의 하위 배열은 (1, 5)이며, nums[1..5] 구간의 최솟값은 4이고 구간의 길이는 5이므로 점수는 4 × (5 − 1 + 1) = 20이 됩니다.
접근 방법: 투 포인터(Two Pointer)
이 문제는 인덱스 k를 기준으로 왼쪽과 오른쪽으로 동시에 확장해 나가는 투 포인터 기법으로 효율적으로 해결할 수 있습니다. 현재까지 탐색한 구간의 최솟값(minNum)을 추적하면서, 구간을 확장할 때마다 좌우 후보 값 중 더 큰 쪽으로 최솟값을 갱신하고 그에 따른 점수를 계산합니다.
알고리즘 단계
ans := nums[k],minNum := nums[k]로 초기화합니다.두 포인터를
i := k,j := k로 설정합니다.i > -1또는j < len(nums)인 동안 아래 과정을 반복합니다.왼쪽 확장:
nums[i] >= minNum인 동안i -= 1을 수행합니다.오른쪽 확장:
nums[j] >= minNum인 동안j += 1을 수행합니다.ans := max(ans, (j - i - 1) * minNum)으로 정답을 갱신합니다.왼쪽 값(nums[i])과 오른쪽 값(nums[j]) 중 더 큰 값을 새로운
minNum으로 설정하며, 포인터가 범위를 벗어난 경우에는 -1을 사용합니다.반복이 종료되면
ans를 반환합니다.
파이썬 구현 코드
다음 구현 예제를 통해 더 자세히 이해해 보겠습니다.
def solve(nums, k):
ans = nums[k]
minNum = nums[k]
i = k
j = k
while i > -1 or j < len(nums):
while i > -1 and nums[i] >= minNum:
i -= 1
while j < len(nums) and nums[j] >= minNum:
j += 1
ans = max(ans, (j - i - 1) * minNum)
minNum = max(nums[i] if i > -1 else -1, nums[j] if j <
len(nums) else -1)
return ans
nums = [2,5,4,8,5,6]
k = 3
print(solve(nums, k))입력
[2,5,4,8,5,6], 3
출력
20