You are given an array nums of n integers and two integers k and x.
The x-sum of an array is calculated by the following procedure:
Count the occurrences of all elements in the array.
Keep only the occurrences of the top x most frequent elements.
If two elements have the same number of occurrences,
the element with the bigger value is considered more frequent.
Calculate the sum of the resulting array.
Note that if an array has less than x distinct elements, its x-sum is the sum of the array.
Return an integer array answer of length n - k + 1 where answer[i] is the x-sum of the subarray nums[i..i + k - 1].
nums = [1,1,2,2,3,4,2,3], k = 6, x = 2
[1, 1, 2, 2, 3, 4]1 + 1 + 2 + 2 = 6[1, 2, 2, 3, 4, 2]2 + 2 + 2 + 4 = 10[2, 2, 3, 4, 2, 3]2 + 2 + 2 + 3 + 3 = 12from sortedcontainers import SortedList
class Solver:
def __init__(self, limit: int):
self.r = SortedList()
self.t = SortedList()
self.c = 0
self.f = dict()
self.limit = limit
def update(self, val: int, update: int):
if val in self.f:
if (self.f[val], val) in self.t:
self.t.remove((self.f[val], val))
self.c -= self.f[val] * val
else:
self.r.remove((self.f[val], val))
if val not in self.f:
self.f[val] = 0
self.f[val] += update
if self.f[val] == 0:
del self.f[val]
else:
self.t.add((self.f[val], val))
self.c += self.f[val] * val
self.balance()
def balance(self):
if len(self.t) > self.limit:
f, v = self.t.pop(0)
self.c -= f * v
self.r.add((f, v))
if len(self.t) < self.limit and self.r:
f, v = self.r.pop()
self.c += f * v
self.t.add((f, v))
if self.t and self.r and self.t[0] < self.r[-1]:
top = self.t.pop(0)
remain = self.r.pop()
self.t.add(remain)
self.r.add(top)
self.c = self.c - top[0] * top[1] + remain[0] * remain[1]
class Solution:
def findXSum(self, nums: List[int], k: int, x: int) -> List[int]:
ans = []
s = Solver(x)
for i in range(k):
s.update(nums[i], 1)
ans.append(s.c)
for i in range(k, len(nums)):
s.update(nums[i], 1)
s.update(nums[i - k], -1)
ans.append(s.c)
return ans
슬라이딩 윈도우 내에서 각 원소의 빈도를 계속 갱신하면서, 그중 상위 x개의 (freq, val)만 유지하고 이들의 freq * val 합을 효율적으로 계산하는 방식으로 동작합니다.
정렬된 두 그룹을 사용합니다:
원소를 추가하거나 제거하면 빈도가 바뀌므로, 이전 위치(top 또는 rest)에서 제거한 뒤 새 빈도로 다시 넣습니다. 이때 일단 임시로 top에 넣고 균형을 맞춰줍니다.
균형(balancing)은 다음 규칙으로 유지됩니다:
top 안의 원소들에 대해 freq * val의 합을 c로 유지하기 때문에, 슬라이딩 이동 시 전체 정렬을 다시 하지 않고도 O(log U) 비용으로 결과를 업데이트할 수 있습니다.