diff --git a/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/README.md b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/README.md index 9881df4ecbcc2..c12ce9f630e2d 100644 --- a/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/README.md +++ b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/README.md @@ -184,32 +184,206 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3600-3699/3672.Su -### 方法一 +### 方法一:哈希表 + 优先队列 + 滑动窗口 + 懒删除 + +我们用一个哈希表 $\textit{cnt}$ 记录当前窗口中每个数字的出现次数。我们用一个优先队列 $\textit{pq}$ 记录当前窗口中每个数字的出现次数和数字本身,优先级为出现次数从大到小,如果出现次数相同,则数字从小到大。 + +我们设计一个函数 $\textit{get\_mode()}$,用于获取当前窗口的众数及其出现次数。具体做法是不断弹出优先队列的堆顶元素,直到堆顶元素的出现次数与哈希表中记录的出现次数相同为止,此时堆顶元素即为当前窗口的众数及其出现次数。 + +我们用一个变量 $\textit{ans}$ 记录所有窗口的权重和。初始时,我们将数组的前 $k$ 个数字加入哈希表和优先队列中,然后调用 $\textit{get\_mode()}$ 获取第一个窗口的众数及其出现次数,并将其权重加入 $\textit{ans}$。 + +然后,我们从数组的第 $k$ 个数字开始,依次将每个数字加入哈希表和优先队列中,同时将窗口的左端数字从哈希表中删除(出现次数减一)。然后调用 $\textit{get\_mode()}$ 获取当前窗口的众数及其出现次数,并将其权重加入 $\textit{ans}$。 + +最后,返回 $\textit{ans}$。 + +时间复杂度 $O(n \log k)$,其中 $n$ 是数组的长度。空间复杂度 $O(k)$。 #### Python3 ```python - +class Solution: + def modeWeight(self, nums: List[int], k: int) -> int: + pq = [] + cnt = defaultdict(int) + for x in nums[:k]: + cnt[x] += 1 + heappush(pq, (-cnt[x], x)) + + def get_mode() -> int: + while -pq[0][0] != cnt[pq[0][1]]: + heappop(pq) + freq, val = -pq[0][0], pq[0][1] + return freq * val + + ans = 0 + ans += get_mode() + + for i in range(k, len(nums)): + x, y = nums[i], nums[i - k] + cnt[x] += 1 + cnt[y] -= 1 + heappush(pq, (-cnt[x], x)) + heappush(pq, (-cnt[y], y)) + + ans += get_mode() + + return ans ``` #### Java ```java - +class Solution { + public long modeWeight(int[] nums, int k) { + Map cnt = new HashMap<>(); + PriorityQueue pq = new PriorityQueue<>( + (a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1])); + + for (int i = 0; i < k; i++) { + int x = nums[i]; + cnt.merge(x, 1, Integer::sum); + pq.offer(new int[] {-cnt.get(x), x}); + } + + long ans = 0; + + Supplier getMode = () -> { + while (true) { + int[] top = pq.peek(); + int val = top[1]; + int freq = -top[0]; + if (cnt.getOrDefault(val, 0) == freq) { + return 1L * freq * val; + } + pq.poll(); + } + }; + + ans += getMode.get(); + + for (int i = k; i < nums.length; i++) { + int x = nums[i], y = nums[i - k]; + cnt.merge(x, 1, Integer::sum); + pq.offer(new int[] {-cnt.get(x), x}); + cnt.merge(y, -1, Integer::sum); + pq.offer(new int[] {-cnt.get(y), y}); + ans += getMode.get(); + } + + return ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + long long modeWeight(vector& nums, int k) { + unordered_map cnt; + priority_queue> pq; // {freq, -val} + + for (int i = 0; i < k; i++) { + int x = nums[i]; + cnt[x]++; + pq.push({cnt[x], -x}); + } + + auto get_mode = [&]() { + while (true) { + auto [freq, negVal] = pq.top(); + int val = -negVal; + if (cnt[val] == freq) { + return 1LL * freq * val; + } + pq.pop(); + } + }; + + long long ans = 0; + ans += get_mode(); + + for (int i = k; i < nums.size(); i++) { + int x = nums[i], y = nums[i - k]; + cnt[x]++; + cnt[y]--; + pq.push({cnt[x], -x}); + pq.push({cnt[y], -y}); + ans += get_mode(); + } + + return ans; + } +}; ``` #### Go ```go - +func modeWeight(nums []int, k int) int64 { + cnt := make(map[int]int) + pq := &MaxHeap{} + heap.Init(pq) + + for i := 0; i < k; i++ { + x := nums[i] + cnt[x]++ + heap.Push(pq, pair{cnt[x], x}) + } + + getMode := func() int64 { + for { + top := (*pq)[0] + if cnt[top.val] == top.freq { + return int64(top.freq) * int64(top.val) + } + heap.Pop(pq) + } + } + + var ans int64 + ans += getMode() + + for i := k; i < len(nums); i++ { + x, y := nums[i], nums[i-k] + cnt[x]++ + cnt[y]-- + heap.Push(pq, pair{cnt[x], x}) + heap.Push(pq, pair{cnt[y], y}) + ans += getMode() + } + + return ans +} + +type pair struct { + freq int + val int +} + +type MaxHeap []pair + +func (h MaxHeap) Len() int { return len(h) } +func (h MaxHeap) Less(i, j int) bool { + if h[i].freq != h[j].freq { + return h[i].freq > h[j].freq + } + return h[i].val < h[j].val +} +func (h MaxHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *MaxHeap) Push(x any) { + *h = append(*h, x.(pair)) +} +func (h *MaxHeap) Pop() any { + old := *h + n := len(old) + x := old[n-1] + *h = old[:n-1] + return x +} ``` diff --git a/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/README_EN.md b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/README_EN.md index 7420a94a48283..9645c426892f5 100644 --- a/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/README_EN.md +++ b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/README_EN.md @@ -184,32 +184,206 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3600-3699/3672.Su -### Solution 1 +### Solution 1: Hash Map + Priority Queue + Sliding Window + Lazy Deletion + +We use a hash map $\textit{cnt}$ to record the frequency of each number in the current window. We use a priority queue $\textit{pq}$ to store the frequency and value of each number in the current window, with priority given to higher frequency, and for equal frequency, to smaller numbers. + +We design a function $\textit{get_mode()}$ to obtain the mode and its frequency in the current window. Specifically, we repeatedly pop the top element from the priority queue until its frequency matches the frequency recorded in the hash map; at that point, the top element is the mode and its frequency for the current window. + +We use a variable $\textit{ans}$ to record the sum of weights for all windows. Initially, we add the first $k$ numbers of the array to the hash map and priority queue, then call $\textit{get_mode()}$ to get the mode and its frequency for the first window, and add its weight to $\textit{ans}$. + +Next, starting from the $k$-th number, we add each number to the hash map and priority queue, and decrement the frequency of the leftmost number in the window in the hash map. Then, we call $\textit{get_mode()}$ to get the mode and its frequency for the current window, and add its weight to $\textit{ans}$. + +Finally, we return $\textit{ans}$. + +The time complexity is $O(n \log k)$, and the space complexity is $O(k)$. #### Python3 ```python - +class Solution: + def modeWeight(self, nums: List[int], k: int) -> int: + pq = [] + cnt = defaultdict(int) + for x in nums[:k]: + cnt[x] += 1 + heappush(pq, (-cnt[x], x)) + + def get_mode() -> int: + while -pq[0][0] != cnt[pq[0][1]]: + heappop(pq) + freq, val = -pq[0][0], pq[0][1] + return freq * val + + ans = 0 + ans += get_mode() + + for i in range(k, len(nums)): + x, y = nums[i], nums[i - k] + cnt[x] += 1 + cnt[y] -= 1 + heappush(pq, (-cnt[x], x)) + heappush(pq, (-cnt[y], y)) + + ans += get_mode() + + return ans ``` #### Java ```java - +class Solution { + public long modeWeight(int[] nums, int k) { + Map cnt = new HashMap<>(); + PriorityQueue pq = new PriorityQueue<>( + (a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1])); + + for (int i = 0; i < k; i++) { + int x = nums[i]; + cnt.merge(x, 1, Integer::sum); + pq.offer(new int[] {-cnt.get(x), x}); + } + + long ans = 0; + + Supplier getMode = () -> { + while (true) { + int[] top = pq.peek(); + int val = top[1]; + int freq = -top[0]; + if (cnt.getOrDefault(val, 0) == freq) { + return 1L * freq * val; + } + pq.poll(); + } + }; + + ans += getMode.get(); + + for (int i = k; i < nums.length; i++) { + int x = nums[i], y = nums[i - k]; + cnt.merge(x, 1, Integer::sum); + pq.offer(new int[] {-cnt.get(x), x}); + cnt.merge(y, -1, Integer::sum); + pq.offer(new int[] {-cnt.get(y), y}); + ans += getMode.get(); + } + + return ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + long long modeWeight(vector& nums, int k) { + unordered_map cnt; + priority_queue> pq; // {freq, -val} + + for (int i = 0; i < k; i++) { + int x = nums[i]; + cnt[x]++; + pq.push({cnt[x], -x}); + } + + auto get_mode = [&]() { + while (true) { + auto [freq, negVal] = pq.top(); + int val = -negVal; + if (cnt[val] == freq) { + return 1LL * freq * val; + } + pq.pop(); + } + }; + + long long ans = 0; + ans += get_mode(); + + for (int i = k; i < nums.size(); i++) { + int x = nums[i], y = nums[i - k]; + cnt[x]++; + cnt[y]--; + pq.push({cnt[x], -x}); + pq.push({cnt[y], -y}); + ans += get_mode(); + } + + return ans; + } +}; ``` #### Go ```go - +func modeWeight(nums []int, k int) int64 { + cnt := make(map[int]int) + pq := &MaxHeap{} + heap.Init(pq) + + for i := 0; i < k; i++ { + x := nums[i] + cnt[x]++ + heap.Push(pq, pair{cnt[x], x}) + } + + getMode := func() int64 { + for { + top := (*pq)[0] + if cnt[top.val] == top.freq { + return int64(top.freq) * int64(top.val) + } + heap.Pop(pq) + } + } + + var ans int64 + ans += getMode() + + for i := k; i < len(nums); i++ { + x, y := nums[i], nums[i-k] + cnt[x]++ + cnt[y]-- + heap.Push(pq, pair{cnt[x], x}) + heap.Push(pq, pair{cnt[y], y}) + ans += getMode() + } + + return ans +} + +type pair struct { + freq int + val int +} + +type MaxHeap []pair + +func (h MaxHeap) Len() int { return len(h) } +func (h MaxHeap) Less(i, j int) bool { + if h[i].freq != h[j].freq { + return h[i].freq > h[j].freq + } + return h[i].val < h[j].val +} +func (h MaxHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *MaxHeap) Push(x any) { + *h = append(*h, x.(pair)) +} +func (h *MaxHeap) Pop() any { + old := *h + n := len(old) + x := old[n-1] + *h = old[:n-1] + return x +} ``` diff --git a/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.cpp b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.cpp new file mode 100644 index 0000000000000..9f9407df125d7 --- /dev/null +++ b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.cpp @@ -0,0 +1,38 @@ +class Solution { +public: + long long modeWeight(vector& nums, int k) { + unordered_map cnt; + priority_queue> pq; // {freq, -val} + + for (int i = 0; i < k; i++) { + int x = nums[i]; + cnt[x]++; + pq.push({cnt[x], -x}); + } + + auto get_mode = [&]() { + while (true) { + auto [freq, negVal] = pq.top(); + int val = -negVal; + if (cnt[val] == freq) { + return 1LL * freq * val; + } + pq.pop(); + } + }; + + long long ans = 0; + ans += get_mode(); + + for (int i = k; i < nums.size(); i++) { + int x = nums[i], y = nums[i - k]; + cnt[x]++; + cnt[y]--; + pq.push({cnt[x], -x}); + pq.push({cnt[y], -y}); + ans += get_mode(); + } + + return ans; + } +}; diff --git a/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.go b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.go new file mode 100644 index 0000000000000..e2a97f0e72b8a --- /dev/null +++ b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.go @@ -0,0 +1,61 @@ +func modeWeight(nums []int, k int) int64 { + cnt := make(map[int]int) + pq := &MaxHeap{} + heap.Init(pq) + + for i := 0; i < k; i++ { + x := nums[i] + cnt[x]++ + heap.Push(pq, pair{cnt[x], x}) + } + + getMode := func() int64 { + for { + top := (*pq)[0] + if cnt[top.val] == top.freq { + return int64(top.freq) * int64(top.val) + } + heap.Pop(pq) + } + } + + var ans int64 + ans += getMode() + + for i := k; i < len(nums); i++ { + x, y := nums[i], nums[i-k] + cnt[x]++ + cnt[y]-- + heap.Push(pq, pair{cnt[x], x}) + heap.Push(pq, pair{cnt[y], y}) + ans += getMode() + } + + return ans +} + +type pair struct { + freq int + val int +} + +type MaxHeap []pair + +func (h MaxHeap) Len() int { return len(h) } +func (h MaxHeap) Less(i, j int) bool { + if h[i].freq != h[j].freq { + return h[i].freq > h[j].freq + } + return h[i].val < h[j].val +} +func (h MaxHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *MaxHeap) Push(x any) { + *h = append(*h, x.(pair)) +} +func (h *MaxHeap) Pop() any { + old := *h + n := len(old) + x := old[n-1] + *h = old[:n-1] + return x +} diff --git a/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.java b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.java new file mode 100644 index 0000000000000..b335c70d8a3ed --- /dev/null +++ b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.java @@ -0,0 +1,40 @@ +class Solution { + public long modeWeight(int[] nums, int k) { + Map cnt = new HashMap<>(); + PriorityQueue pq = new PriorityQueue<>( + (a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1])); + + for (int i = 0; i < k; i++) { + int x = nums[i]; + cnt.merge(x, 1, Integer::sum); + pq.offer(new int[] {-cnt.get(x), x}); + } + + long ans = 0; + + Supplier getMode = () -> { + while (true) { + int[] top = pq.peek(); + int val = top[1]; + int freq = -top[0]; + if (cnt.getOrDefault(val, 0) == freq) { + return 1L * freq * val; + } + pq.poll(); + } + }; + + ans += getMode.get(); + + for (int i = k; i < nums.length; i++) { + int x = nums[i], y = nums[i - k]; + cnt.merge(x, 1, Integer::sum); + pq.offer(new int[] {-cnt.get(x), x}); + cnt.merge(y, -1, Integer::sum); + pq.offer(new int[] {-cnt.get(y), y}); + ans += getMode.get(); + } + + return ans; + } +} diff --git a/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.py b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.py new file mode 100644 index 0000000000000..e4cc87dc70d8b --- /dev/null +++ b/solution/3600-3699/3672.Sum of Weighted Modes in Subarrays/Solution.py @@ -0,0 +1,27 @@ +class Solution: + def modeWeight(self, nums: List[int], k: int) -> int: + pq = [] + cnt = defaultdict(int) + for x in nums[:k]: + cnt[x] += 1 + heappush(pq, (-cnt[x], x)) + + def get_mode() -> int: + while -pq[0][0] != cnt[pq[0][1]]: + heappop(pq) + freq, val = -pq[0][0], pq[0][1] + return freq * val + + ans = 0 + ans += get_mode() + + for i in range(k, len(nums)): + x, y = nums[i], nums[i - k] + cnt[x] += 1 + cnt[y] -= 1 + heappush(pq, (-cnt[x], x)) + heappush(pq, (-cnt[y], y)) + + ans += get_mode() + + return ans