nums of length n.
Construct an array prefixGcd where for each index i:
mxi = max(nums[0], nums[1], ..., nums[i]).prefixGcd[i] = gcd(nums[i], mxi).After constructing prefixGcd:
prefixGcd in non-decreasing order.gcd of the two elements.n is odd, the middle element in the prefixGcd array remains unpaired and should be ignored.Return an integer denoting the sum of the GCD values of all formed pairs.
The term gcd(a, b) denotes the greatest common divisor of a and b.
Example 1:
Output: 2
Explanation:
Construct prefixGcd:
i | nums[i] | mxi | prefixGcd[i] |
|---|---|---|---|
| 0 | 2 | 2 | 2 |
| 1 | 6 | 6 | 6 |
| 2 | 4 | 6 | 2 |
prefixGcd = [2, 6, 2]. After sorting, it forms [2, 2, 6].
Pair the smallest and largest elements: gcd(2, 6) = 2. The remaining middle element 2 is ignored. Thus, the sum is 2.
Example 2:
Output: 5
Explanation:
Construct prefixGcd:
i | nums[i] | mxi | prefixGcd[i] |
|---|---|---|---|
| 0 | 3 | 3 | 3 |
| 1 | 6 | 6 | 6 |
| 2 | 2 | 6 | 2 |
| 3 | 8 | 8 | 8 |
prefixGcd = [3, 6, 2, 8]. After sorting, it forms [2, 3, 6, 8].
Form pairs: gcd(2, 8) = 2 and gcd(3, 6) = 3. Thus, the sum is 2 + 3 = 5.
Constraints:
1 <= n == nums.length <= 1051 <= nums[i] <= 109배열, 수학, 투 포인터, 정렬, 시뮬레이션, 정수론
주어진 정수 배열 nums를 이용해 prefixGcd 배열을 구성하는 문제입니다.
nums (길이 n, 1 ≤ n ≤ 100,000, 원소 값 1 ~ 10^9)과정 요약:
i까지의 최댓값 mx_i를 구하고, gcd(nums[i], mx_i)를 계산해 prefixGcd 배열을 만듭니다.prefixGcd를 오름차순으로 정렬합니다.n이 홀수면 중간 값은 무시합니다.이 문제는 시뮬레이션과 투 포인터 기법을 그대로 구현하면 됩니다.
mx)을 유지합니다. 각 원소에 대해 gcd(현재 원소, mx)를 계산해 리스트에 저장합니다. 이 과정은 O(n) 시간에 가능합니다.prefixGcd 배열을 정렬합니다. O(n log n) 시간이 소요됩니다.left=0, right=n-1)에서 시작해 가운데로 모이며 GCD를 계산하고 누적합니다. left < right 조건으로 홀수 개수일 때 중간 원소가 자연스럽게 제외되도록 합니다. O(n) 시간에 처리됩니다.자료구조는 단순한 리스트(prefixGcd)만 사용하면 충분하며, 파이썬의 math.gcd 함수를 활용해 최대공약수를 효율적으로 계산합니다.
mx를 0으로 초기화하고 prefixGcd 빈 리스트를 준비합니다.nums를 순회하며 mx = max(mx, nums[i])로 현재까지의 최댓값을 갱신합니다.math.gcd(mx, nums[i])를 계산해 prefixGcd에 추가합니다.prefixGcd 리스트를 sort() 메서드로 오름차순 정렬합니다.n-1에 위치하게 됩니다.left = 0, right = n - 1로 양 끝 인덱스를 초기화하고 answer = 0으로 합계를 준비합니다.while left < right: 반복문을 실행합니다. (같아지면 중복/중간 원소이므로 중단)math.gcd(prefixGcd[left], prefixGcd[right])를 계산해 answer에 더합니다.left는 1 증가시키고, right는 1 감소시켜 다음 쌍으로 이동합니다.answer를 반환합니다.시간 복잡도: O(n log n)
prefixGcd 구성: 배열을 한 번 순회하므로 **O(n)**입니다. (math.gcd는 로그 시간이지만 상수로 간주)공간 복잡도: O(n)
prefixGcd 리스트를 저장하기 위해 입력 크기 n에 비례하는 추가 공간이 필요합니다.i까지 최댓값을 찾는 O(n^2) 방식이 아닌, 변수 하나(mx)로 현재까지의 최댓값을 갱신하며 O(1)에 구하는 것이 핵심입니다.while left < right 조건을 사용하면 left == right가 되는 순간(가운데 원소) 루프가 종료되므로, 별도의 분기 처리 없이 중간 원소를 자연스럽게 무시할 수 있습니다.import math
class Solution:
def gcdSum(self, nums: list[int]) -> int:
n = len(nums)
mx = 0
prefixGcd = []
for i in range(n):
mx = max(mx, nums[i])
prefixGcd.append(math.gcd(mx,nums[i]))
left = 0
right = n - 1
answer = 0
prefixGcd.sort()
while left < right:
answer += math.gcd(prefixGcd[left], prefixGcd[right])
left += 1
right -= 1
return answer