728x90

https://leetcode.com/problems/maximum-sum-circular-subarray/

 

해당 문제는 kadane 알고리즘 방법으로 접근하여 문제를 해결 하였습니다.

 

Approach

 

  • Kadane's algorithm을 사용하여 일반적인 최대 부분합을 O(n)에 구합니다.
  • 순환하는 경우는 전체 합에서 최소 부분합을 빼서 구합니다.
  • 모든 원소가 음수인 경우는 별도로 처리합니다.

시간복잡도: O(n) 공간복잡도: O(1)

  1. 전체 배열의 합 (total): 5 + (-3) + 5 = 7
  2. 최소 부분합 (minSum): -3
    • 연속된 부분 배열 중 가장 작은 합
  3. total - minSum = 7 - (-3) = 10
    • 이것이 바로 [5,5]를 선택했을 때의 합과 같습니다!

이렇게 되는 이유는:

  1. 순환 배열에서 양 끝의 원소들을 선택하려면 (예: [5,5])
  2. 중간에 있는 원소들을 제외해야 합니다 (예: [-3])
  3. 중간의 원소들을 제외하는 가장 좋은 방법은 "최소 부분합"을 찾아서 제거하는 것입니다
  4. 따라서 "전체 합 - 최소 부분합"이 순환 배열에서 가능한 최대 부분합이 됩니다

이 방식은 다음과 같은 장점이 있습니다:

  • 한 번의 순회로 최소 부분합을 찾을 수 있습니다 (O(n))
  • 전체 합도 한 번의 순회로 구할 수 있습니다 (O(n))
  • 추가 메모리를 사용하지 않습니다 (O(1))

 

 

 

func maxSubarraySumCircular(nums []int) int {
	if len(nums) == 0 {
		return 0
	}

	kadane := func(nums []int, findMax bool) int {
		curr := nums[0]
		result := nums[0]

		for i := 1; i < len(nums); i++ {
			if findMax {
				curr = max(nums[i], curr+nums[i])
				result = max(curr, result)
			} else {
				curr = min(nums[i], curr+nums[i])
				result = min(curr, result)
			}
		}
		return result
	}

	findMax := kadane(nums, true)
	if findMax < 0 {
		return findMax
	}

	totalSum := 0

	for _, num := range nums {
		totalSum += num
	}

	findMin := kadane(nums, false)
	return max(findMax, totalSum-findMin)
}
728x90