Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bf876cb

Browse files
feat: add solutions to lc problems: No.3318,3321 (doocs#3642)
* No.3318.Find X-Sum of All K-Long Subarrays I * No.3321.Find X-Sum of All K-Long Subarrays II
1 parent 3bdfd2a commit bf876cb

File tree

11 files changed

+1801
-16
lines changed

11 files changed

+1801
-16
lines changed

‎solution/3000-3099/3013.Divide an Array Into Subarrays With Minimum Cost II/README.md‎

Lines changed: 671 additions & 0 deletions
Large diffs are not rendered by default.

‎solution/3300-3399/3318.Find X-Sum of All K-Long Subarrays I/README.md‎

Lines changed: 192 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,26 +76,214 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3318.Fi
7676

7777
<!-- solution:start -->
7878

79-
### 方法一
79+
### 方法一:哈希表 + 有序集合
80+
81+
我们用一个哈希表 $\textit{cnt}$ 统计窗口中每个元素的出现次数,用一个有序集合 $\textit{l}$ 存储窗口中出现次数最多的 $x$ 个元素,用另一个有序集合 $\textit{r}$ 存储剩余的元素。
82+
83+
我们维护一个变量 $\textit{s}$ 表示 $\textit{l}$ 中元素的和。初始时,我们将前 $k$ 个元素加入到窗口中,并且更新有序集合 $\textit{l}$ 和 $\textit{r},ドル并且计算 $\textit{s}$ 的值。如果 $\textit{l}$ 的大小小于 $x,ドル并且 $\textit{r}$ 不为空,我们就循环将 $\textit{r}$ 中的最大元素移动到 $\textit{l}$ 中,直到 $\textit{l}$ 的大小等于 $x,ドル过程中更新 $\textit{s}$ 的值。如果 $\textit{l}$ 的大小大于 $x,ドル我们就循环将 $\textit{l}$ 中的最小元素移动到 $\textit{r}$ 中,直到 $\textit{l}$ 的大小等于 $x,ドル过程中更新 $\textit{s}$ 的值。此时,我们就可以计算出当前窗口的 $\textit{x-sum},ドル添加到答案数组中。然后我们将窗口的左边界元素移出,更新 $\textit{cnt},ドル并且更新有序集合 $\textit{l}$ 和 $\textit{r},ドル以及 $\textit{s}$ 的值。继续遍历数组,直到遍历结束。
84+
85+
时间复杂度 $O(n \times \log k),ドル空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。
86+
87+
相似题目:
88+
89+
- [3013. 将数组分成最小总代价的子数组 II](/solution/3000-3099/3013.Divide%20an%20Array%20Into%20Subarrays%20With%20Minimum%20Cost%20II/README.md)
8090

8191
<!-- tabs:start -->
8292

8393
#### Python3
8494

8595
```python
86-
96+
from sortedcontainers import SortedList
97+
98+
99+
class Solution:
100+
def findXSum(self, nums: List[int], k: int, x: int) -> List[int]:
101+
def add(v: int):
102+
if cnt[v] == 0:
103+
return
104+
p = (cnt[v], v)
105+
if l and p > l[0]:
106+
nonlocal s
107+
s += p[0] * p[1]
108+
l.add(p)
109+
else:
110+
r.add(p)
111+
112+
def remove(v: int):
113+
if cnt[v] == 0:
114+
return
115+
p = (cnt[v], v)
116+
if p in l:
117+
nonlocal s
118+
s -= p[0] * p[1]
119+
l.remove(p)
120+
else:
121+
r.remove(p)
122+
123+
l = SortedList()
124+
r = SortedList()
125+
cnt = Counter()
126+
s = 0
127+
n = len(nums)
128+
ans = [0] * (n - k + 1)
129+
for i, v in enumerate(nums):
130+
remove(v)
131+
cnt[v] += 1
132+
add(v)
133+
j = i - k + 1
134+
if j < 0:
135+
continue
136+
while r and len(l) < x:
137+
p = r.pop()
138+
l.add(p)
139+
s += p[0] * p[1]
140+
while len(l) > x:
141+
p = l.pop(0)
142+
s -= p[0] * p[1]
143+
r.add(p)
144+
ans[j] = s
145+
146+
remove(nums[j])
147+
cnt[nums[j]] -= 1
148+
add(nums[j])
149+
return ans
87150
```
88151

89152
#### Java
90153

91154
```java
92-
155+
class Solution {
156+
private TreeSet<int[]> l = new TreeSet<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
157+
private TreeSet<int[]> r = new TreeSet<>(l.comparator());
158+
private Map<Integer, Integer> cnt = new HashMap<>();
159+
private int s;
160+
161+
public int[] findXSum(int[] nums, int k, int x) {
162+
int n = nums.length;
163+
int[] ans = new int[n - k + 1];
164+
for (int i = 0; i < n; ++i) {
165+
int v = nums[i];
166+
remove(v);
167+
cnt.merge(v, 1, Integer::sum);
168+
add(v);
169+
int j = i - k + 1;
170+
if (j < 0) {
171+
continue;
172+
}
173+
while (!r.isEmpty() && l.size() < x) {
174+
var p = r.pollLast();
175+
s += p[0] * p[1];
176+
l.add(p);
177+
}
178+
while (l.size() > x) {
179+
var p = l.pollFirst();
180+
s -= p[0] * p[1];
181+
r.add(p);
182+
}
183+
ans[j] = s;
184+
185+
remove(nums[j]);
186+
cnt.merge(nums[j], -1, Integer::sum);
187+
add(nums[j]);
188+
}
189+
return ans;
190+
}
191+
192+
private void remove(int v) {
193+
if (!cnt.containsKey(v)) {
194+
return;
195+
}
196+
var p = new int[] {cnt.get(v), v};
197+
if (l.contains(p)) {
198+
l.remove(p);
199+
s -= p[0] * p[1];
200+
} else {
201+
r.remove(p);
202+
}
203+
}
204+
205+
private void add(int v) {
206+
if (!cnt.containsKey(v)) {
207+
return;
208+
}
209+
var p = new int[] {cnt.get(v), v};
210+
if (!l.isEmpty() && l.comparator().compare(l.first(), p) < 0) {
211+
l.add(p);
212+
s += p[0] * p[1];
213+
} else {
214+
r.add(p);
215+
}
216+
}
217+
}
93218
```
94219

95220
#### C++
96221

97222
```cpp
98-
223+
class Solution {
224+
public:
225+
vector<int> findXSum(vector<int>& nums, int k, int x) {
226+
using pii = pair<int, int>;
227+
set<pii> l, r;
228+
int s = 0;
229+
unordered_map<int, int> cnt;
230+
auto add = [&](int v) {
231+
if (cnt[v] == 0) {
232+
return;
233+
}
234+
pii p = {cnt[v], v};
235+
if (!l.empty() && p > *l.begin()) {
236+
s += p.first * p.second;
237+
l.insert(p);
238+
} else {
239+
r.insert(p);
240+
}
241+
};
242+
auto remove = [&](int v) {
243+
if (cnt[v] == 0) {
244+
return;
245+
}
246+
pii p = {cnt[v], v};
247+
auto it = l.find(p);
248+
if (it != l.end()) {
249+
s -= p.first * p.second;
250+
l.erase(it);
251+
} else {
252+
r.erase(p);
253+
}
254+
};
255+
vector<int> ans;
256+
for (int i = 0; i < nums.size(); ++i) {
257+
remove(nums[i]);
258+
++cnt[nums[i]];
259+
add(nums[i]);
260+
261+
int j = i - k + 1;
262+
if (j < 0) {
263+
continue;
264+
}
265+
266+
while (!r.empty() && l.size() < x) {
267+
pii p = *r.rbegin();
268+
s += p.first * p.second;
269+
r.erase(p);
270+
l.insert(p);
271+
}
272+
while (l.size() > x) {
273+
pii p = *l.begin();
274+
s -= p.first * p.second;
275+
l.erase(p);
276+
r.insert(p);
277+
}
278+
ans.push_back(s);
279+
280+
remove(nums[j]);
281+
--cnt[nums[j]];
282+
add(nums[j]);
283+
}
284+
return ans;
285+
}
286+
};
99287
```
100288

101289
#### Go

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /