Skip to content

Commit ffb288d

Browse files
authored
update: 添加问题“3186.施咒的最大总伤害”的代码和题解 (#1168)
* word: yesterday (#1166) * word: today (#1166) * 3186: init (#1167) * 3186: half.cpp (#1167) - 可以不这么写 * 3186: WA.cpp (#1167) 使用power[i]不是不能使用power[i - 1],而是不能使用power[i] - 1 * 3186: dbg.cpp (#1167) - 尝试使用c20的ranges::失败 * 3186: AC.cpp (#1167) - AC,88.61%,87.17% * 3186: CE.py (#1167) * 3186: CE.py (#1167) * 3186: RE.py (#1167) * 3186: AC.py (#1167) - AC,88.63%,62.94% * 3186: WA.py O(1)空间 (#1167) * 3186: AC.py O(1)空间 (#1167) - AC,O(1)空间,98.02%,97.69% * update: 添加问题“3186.施咒的最大总伤害”的代码和题解 (#1168) Signed-off-by: LetMeFly666 <[email protected]> * word(fix): 这个是v. ,前面的exempt是adj --------- Signed-off-by: LetMeFly666 <[email protected]>
1 parent f23c324 commit ffb288d

8 files changed

+276
-2
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2025-10-11 18:10:29
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2025-10-11 18:38:56
6+
*/
7+
#if defined(_WIN32) || defined(__APPLE__)
8+
#include "_[1,2]toVector.h"
9+
#include <algorithm>
10+
#endif
11+
12+
typedef long long ll;
13+
class Solution {
14+
public:
15+
ll maximumTotalDamage(vector<int>& power) {
16+
unordered_map<int, int> cnt;
17+
for (int t : power) {
18+
cnt[t]++;
19+
}
20+
vector<pair<int, int>> values(cnt.begin(), cnt.end());
21+
sort(values.begin(), values.end());
22+
vector<ll> dp(values.size() + 1);
23+
for (int i = 0, j = 0; i < values.size(); i++) {
24+
auto& [value, times] = values[i];
25+
while (values[j].first < value - 2) {
26+
j++;
27+
}
28+
dp[i + 1] = max(dp[i], dp[j] + (ll) value * times);
29+
}
30+
return dp.back();
31+
}
32+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
'''
2+
Author: LetMeFly
3+
Date: 2025-10-11 18:10:29
4+
LastEditors: LetMeFly.xyz
5+
LastEditTime: 2025-10-11 18:46:52
6+
'''
7+
from typing import List
8+
from collections import Counter
9+
10+
class Solution:
11+
def maximumTotalDamage(self, power: List[int]) -> int:
12+
cnt = Counter(power)
13+
values = sorted(cnt)
14+
dp = [0] * (len(values) + 1)
15+
j = 0
16+
for i, val in enumerate(values):
17+
while values[j] < val - 2:
18+
j += 1
19+
dp[i + 1] = max(dp[i], dp[j] + val * cnt[val])
20+
return dp[-1]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'''
2+
Author: LetMeFly
3+
Date: 2025-10-11 18:10:29
4+
LastEditors: LetMeFly.xyz
5+
LastEditTime: 2025-10-11 19:04:17
6+
'''
7+
from typing import List
8+
from collections import Counter
9+
10+
class Solution:
11+
def maximumTotalDamage(self, power: List[int]) -> int:
12+
cnt = Counter(power)
13+
values = sorted(cnt)
14+
dp0 = dp1 = dp2 = 0
15+
val1 = val2 = -10
16+
for val in values:
17+
valSum = val * cnt[val]
18+
if val - val2 > 2: # 无冲突
19+
useThis = valSum + dp2
20+
elif val - val1 > 2: # 和val2相差小于2,但和val1不冲突
21+
useThis = valSum + dp1
22+
else: # 和val1、val2都冲突(一定不会再和前面的冲突了)
23+
useThis = valSum + dp0
24+
dp = max(useThis, dp2)
25+
dp0, dp1, dp2 = dp1, dp2, dp
26+
val1, val2 = val2, val
27+
return dp2

Codes/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @Author: LetMeFly
33
* @Date: 2025-08-07 14:11:36
44
* @LastEditors: LetMeFly.xyz
5-
* @LastEditTime: 2025-10-09 23:13:33
5+
* @LastEditTime: 2025-10-11 18:47:55
66
*/
77
pub struct Solution;
88
include!("3494-find-the-minimum-amount-of-time-to-brew-potions.rs"); // 这个fileName是会被脚本替换掉的

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,7 @@
980980
|3181.执行操作可获得的最大总奖励II|困难|<a href="https://leetcode.cn/problems/maximum-total-reward-using-operations-ii/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/10/30/LeetCode%203181.%E6%89%A7%E8%A1%8C%E6%93%8D%E4%BD%9C%E5%8F%AF%E8%8E%B7%E5%BE%97%E7%9A%84%E6%9C%80%E5%A4%A7%E6%80%BB%E5%A5%96%E5%8A%B1II/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/143360617" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/maximum-total-reward-using-operations-ii/solutions/2970967/letmefly-3181zhi-xing-cao-zuo-ke-huo-de-j3vd3/" target="_blank">LeetCode题解</a>|
981981
|3184.构成整天的下标对数目I|简单|<a href="https://leetcode.cn/problems/count-pairs-that-form-a-complete-day-i/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/10/22/LeetCode%203184.%E6%9E%84%E6%88%90%E6%95%B4%E5%A4%A9%E7%9A%84%E4%B8%8B%E6%A0%87%E5%AF%B9%E6%95%B0%E7%9B%AEI/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/143166228" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/count-pairs-that-form-a-complete-day-i/solutions/2961024/letmefly-3184gou-cheng-zheng-tian-de-xia-ujd4/" target="_blank">LeetCode题解</a>|
982982
|3185.构成整天的下标对数目II|中等|<a href="https://leetcode.cn/problems/count-pairs-that-form-a-complete-day-ii/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/10/23/LeetCode%203185.%E6%9E%84%E6%88%90%E6%95%B4%E5%A4%A9%E7%9A%84%E4%B8%8B%E6%A0%87%E5%AF%B9%E6%95%B0%E7%9B%AEII/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/143196224" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/count-pairs-that-form-a-complete-day-ii/solutions/2962770/letmefly-3185gou-cheng-zheng-tian-de-xia-n58t/" target="_blank">LeetCode题解</a>|
983+
|3186.施咒的最大总伤害|中等|<a href="https://leetcode.cn/problems/maximum-total-damage-with-spell-casting/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2025/10/11/LeetCode%203186.%E6%96%BD%E5%92%92%E7%9A%84%E6%9C%80%E5%A4%A7%E6%80%BB%E4%BC%A4%E5%AE%B3/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/153067130" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/maximum-total-damage-with-spell-casting/solutions/3803373/letmefly-3186shi-zhou-de-zui-da-zong-sha-wvjm/" target="_blank">LeetCode题解</a>|
983984
|3191.使二进制数组全部等于1的最少操作次数I|中等|<a href="https://leetcode.cn/problems/minimum-operations-to-make-binary-array-elements-equal-to-one-i/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/10/18/LeetCode%203191.%E4%BD%BF%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%95%B0%E7%BB%84%E5%85%A8%E9%83%A8%E7%AD%89%E4%BA%8E1%E7%9A%84%E6%9C%80%E5%B0%91%E6%93%8D%E4%BD%9C%E6%AC%A1%E6%95%B0I/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/143064645" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/minimum-operations-to-make-binary-array-elements-equal-to-one-i/solutions/2956198/letmefly-3191shi-er-jin-zhi-shu-zu-quan-n822o/" target="_blank">LeetCode题解</a>|
984985
|3192.使二进制数组全部等于1的最少操作次数II|中等|<a href="https://leetcode.cn/problems/minimum-operations-to-make-binary-array-elements-equal-to-one-ii/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/10/19/LeetCode%203192.%E4%BD%BF%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%95%B0%E7%BB%84%E5%85%A8%E9%83%A8%E7%AD%89%E4%BA%8E1%E7%9A%84%E6%9C%80%E5%B0%91%E6%93%8D%E4%BD%9C%E6%AC%A1%E6%95%B0II/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/143066863" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/minimum-operations-to-make-binary-array-elements-equal-to-one-ii/solutions/2956341/letmefly-3192shi-er-jin-zhi-shu-zu-quan-ih15d/" target="_blank">LeetCode题解</a>|
985986
|3194.最小元素和最大元素的最小平均值|简单|<a href="https://leetcode.cn/problems/minimum-average-of-smallest-and-largest-elements/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/10/16/LeetCode%203194.%E6%9C%80%E5%B0%8F%E5%85%83%E7%B4%A0%E5%92%8C%E6%9C%80%E5%A4%A7%E5%85%83%E7%B4%A0%E7%9A%84%E6%9C%80%E5%B0%8F%E5%B9%B3%E5%9D%87%E5%80%BC/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/142994095" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/minimum-average-of-smallest-and-largest-elements/solutions/2953616/letmefly-3194zui-xiao-yuan-su-he-zui-da-6f4v5/" target="_blank">LeetCode题解</a>|
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
---
2+
title: 3186.施咒的最大总伤害:动态规划+双指针——O(1)空间(暂未发现其他O(1)空间的题解)
3+
date: 2025-10-11 19:05:05
4+
tags: [题解, LeetCode, 中等, 数组, 哈希表, map, 双指针, 二分查找, 动态规划, DP, 计数, 排序]
5+
categories: [题解, LeetCode]
6+
---
7+
8+
# 【LetMeFly】3186.施咒的最大总伤害:动态规划+双指针——O(1)空间(暂未发现其他O(1)空间的题解)
9+
10+
力扣题目链接:[https://leetcode.cn/problems/maximum-total-damage-with-spell-casting/](https://leetcode.cn/problems/maximum-total-damage-with-spell-casting/)
11+
12+
<p>一个魔法师有许多不同的咒语。</p>
13+
14+
<p>给你一个数组&nbsp;<code>power</code>&nbsp;,其中每个元素表示一个咒语的伤害值,可能会有多个咒语有相同的伤害值。</p>
15+
16+
<p>已知魔法师使用伤害值为&nbsp;<code>power[i]</code>&nbsp;的咒语时,他们就&nbsp;<strong>不能</strong>&nbsp;使用伤害为&nbsp;<code>power[i] - 2</code>&nbsp;,<code>power[i] - 1</code>&nbsp;,<code>power[i] + 1</code>&nbsp;或者&nbsp;<code>power[i] + 2</code>&nbsp;的咒语。</p>
17+
18+
<p>每个咒语最多只能被使用 <strong>一次</strong>&nbsp;。</p>
19+
20+
<p>请你返回这个魔法师可以达到的伤害值之和的 <strong>最大值</strong>&nbsp;。</p>
21+
22+
<p>&nbsp;</p>
23+
24+
<p><strong class="example">示例 1:</strong></p>
25+
26+
<div class="example-block">
27+
<p><span class="example-io"><b>输入:</b>power = [1,1,3,4]</span></p>
28+
29+
<p><span class="example-io"><b>输出:</b>6</span></p>
30+
31+
<p><strong>解释:</strong></p>
32+
33+
<p>可以使用咒语 0,1,3,伤害值分别为 1,1,4,总伤害值为 6 。</p>
34+
</div>
35+
36+
<p><strong class="example">示例 2:</strong></p>
37+
38+
<div class="example-block">
39+
<p><span class="example-io"><b>输入:</b>power = [7,1,6,6]</span></p>
40+
41+
<p><span class="example-io"><b>输出:</b>13</span></p>
42+
43+
<p><strong>解释:</strong></p>
44+
45+
<p>可以使用咒语 1,2,3,伤害值分别为 1,6,6,总伤害值为 13 。</p>
46+
</div>
47+
48+
<p>&nbsp;</p>
49+
50+
<p><strong>提示:</strong></p>
51+
52+
<ul>
53+
<li><code>1 &lt;= power.length &lt;= 10<sup>5</sup></code></li>
54+
<li><code>1 &lt;= power[i] &lt;= 10<sup>9</sup></code></li>
55+
</ul>
56+
57+
58+
59+
## 解题方法一:动态规划(O(n)空间)
60+
61+
首先二话不说对power数组来个哈希表统计和排序,得到这样的数组:`[<1出现2次>, <3出现1次>, ...]`。排序依据是power小的优先。
62+
63+
创建动态规划数组,dp[i+1]表示power[0]到power[i]所能达到的最大总伤害(dp[0]=0,此处power[i]代表排序后)。
64+
65+
这样就有状态转移方程:
66+
67+
$dp[i+1]=\max(dp[i], dp[j]+thisVal)$
68+
69+
其中$dp[i]$代表不使用当前power,$dp[j]$是最后一个满足$\lt power[i]-2$的power,$thisVal$代表使用这个power产生的总能量($thisVal=power[i]\times times[i]$)。
70+
71+
现在就剩下最后一个问题了,如何快速得到小于$power[i]-2$的最大power是谁,也就是如何得到j的大小。
72+
73+
双指针即可。每当处理一个新$power[i]$时,当$power[j]\lt power[i]-2$时不断另$j+=1$即可。
74+
75+
+ 时间复杂度$O(n\log n)$,其中$n=len(power)$,时间复杂度的来源主要是排序
76+
+ 空间复杂度$O(n)$,空间复杂度的来源主要是动态规划数组
77+
78+
### AC代码
79+
80+
#### C++
81+
82+
```cpp
83+
/*
84+
* @LastEditTime: 2025-10-11 18:38:56
85+
*/
86+
typedef long long ll;
87+
class Solution {
88+
public:
89+
ll maximumTotalDamage(vector<int>& power) {
90+
unordered_map<int, int> cnt;
91+
for (int t : power) {
92+
cnt[t]++;
93+
}
94+
vector<pair<int, int>> values(cnt.begin(), cnt.end());
95+
sort(values.begin(), values.end());
96+
vector<ll> dp(values.size() + 1);
97+
for (int i = 0, j = 0; i < values.size(); i++) {
98+
auto& [value, times] = values[i];
99+
while (values[j].first < value - 2) {
100+
j++;
101+
}
102+
dp[i + 1] = max(dp[i], dp[j] + (ll) value * times);
103+
}
104+
return dp.back();
105+
}
106+
};
107+
108+
```
109+
110+
111+
112+
#### Python
113+
114+
```python
115+
'''
116+
Author: LetMeFly
117+
Date: 2025-10-11 18:10:29
118+
LastEditors: LetMeFly.xyz
119+
LastEditTime: 2025-10-11 18:46:52
120+
'''
121+
from typing import List
122+
from collections import Counter
123+
124+
class Solution:
125+
def maximumTotalDamage(self, power: List[int]) -> int:
126+
cnt = Counter(power)
127+
values = sorted(cnt)
128+
dp = [0] * (len(values) + 1)
129+
j = 0
130+
for i, val in enumerate(values):
131+
while values[j] < val - 2:
132+
j += 1
133+
dp[i + 1] = max(dp[i], dp[j] + val * cnt[val])
134+
return dp[-1]
135+
```
136+
137+
## 解题方法二:动态规划(O(1)空间)
138+
139+
不难发现方法一中空间复杂度的来源主要是动态规划数组,并且不难发现动态规划数组只需要利用到最近几个。
140+
141+
这是因为和power[i]冲突的power范围向前看也就有个$power[i]-1$和$power[i]-2$,假设power中有这两个值,那么至多也就会用到两个前面的dp值。
142+
143+
所以可以使用数个变量来完成dp数组的原地滚动。
144+
145+
+ 时间复杂度$O(n\log n)$,其中$n=len(power)$,时间复杂度的来源主要是排序
146+
+ 空间复杂度$O(1)$,相比于方法一,原地滚动大大简化了动态规划数组所需的空间
147+
148+
### AC代码
149+
150+
#### Python
151+
152+
```python
153+
'''
154+
Author: LetMeFly
155+
Date: 2025-10-11 18:10:29
156+
LastEditors: LetMeFly.xyz
157+
LastEditTime: 2025-10-11 19:04:17
158+
'''
159+
from typing import List
160+
from collections import Counter
161+
162+
class Solution:
163+
def maximumTotalDamage(self, power: List[int]) -> int:
164+
cnt = Counter(power)
165+
values = sorted(cnt)
166+
dp0 = dp1 = dp2 = 0
167+
val1 = val2 = -10
168+
for val in values:
169+
valSum = val * cnt[val]
170+
if val - val2 > 2: # 无冲突
171+
useThis = valSum + dp2
172+
elif val - val1 > 2: # 和val2相差小于2,但和val1不冲突
173+
useThis = valSum + dp1
174+
else: # 和val1、val2都冲突(一定不会再和前面的冲突了)
175+
useThis = valSum + dp0
176+
dp = max(useThis, dp2)
177+
dp0, dp1, dp2 = dp1, dp2, dp
178+
val1, val2 = val2, val
179+
return dp2
180+
```
181+
182+
> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/153067130)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2025/10/11/LeetCode%203186.%E6%96%BD%E5%92%92%E7%9A%84%E6%9C%80%E5%A4%A7%E6%80%BB%E4%BC%A4%E5%AE%B3/)哦~
183+
>
184+
> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode)

Solutions/Other-English-LearningNotes-SomeWords.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1499,13 +1499,21 @@ categories: [自用]
14991499
|||
15001500
|kerosene|n. 煤油|
15011501
|magician|n. 魔术师,术士,巫师|
1502-
|confer|v. 授予,协商,商讨,交换意见<details><summary>例句</summary>The university <font color="#28bea0" title="adj.">conferred</font> an honorary degree <font color="#28bea0" title="adj.">on</font> the scientist after his speech.<audio controls src="https://media-audio1.baydn.com/abc_pri_audio/96682c7a38182f2f2615b0465d747fe4.6c8bec2563bee55b38aa3cf2ac701dbc.mp3"></audio><br/>这所大学在这位科学家演讲完毕后,授予了他荣誉学位。</details>|
1502+
|confer|v. 授予,协商,商讨,交换意见<details><summary>例句</summary>The university <font color="#28bea0">conferred</font> an honorary degree <font color="#28bea0">on</font> the scientist after his speech.<audio controls src="https://media-audio1.baydn.com/abc_pri_audio/96682c7a38182f2f2615b0465d747fe4.6c8bec2563bee55b38aa3cf2ac701dbc.mp3"></audio><br/>这所大学在这位科学家演讲完毕后,授予了他荣誉学位。</details>|
15031503
|||
15041504
|woollen|n. 毛线,毛织品<br/>adj. 羊毛的,毛纺的|
15051505
|||
15061506
|negate|v. 否定,否认,取消,使无效|
15071507
|gust|n. 一阵(风),(感情/气味)突然爆发<br/>v. 猛刮|
15081508
|receptionist|n. 接待员|
1509+
|||
1510+
|tack|n. 图钉;行动方针,方法;航向<br/>v. 用图钉钉住,改变方向|
1511+
|||
1512+
|jumble|n. 杂乱的一堆<br/>v. 使乱堆,使混乱|
1513+
|rummage|v. 乱翻,搜寻<br/>n. 翻找,搜寻<details><summary>例句</summary>The policeman <font color="#28bea0">rummage</font>d through the <font color="#28bea0">jumble</font> of documents on the desk.<audio controls src="https://media-audio1.baydn.com/abc_pri_audio/88423f3f7e1b0ba2b15a2404be8edc26.88423f3f7e1b0ba2b15a2404be8edc26.mp3"></audio><br/>警察在桌子上乱七八糟的文件中翻找。</details>|
1514+
|talkative|adj. 爱说话的,多嘴的,健谈的|
1515+
|plight|n. 困境,苦难<br/>v. 保证,发誓,订婚|
1516+
|potentiality|n. 潜在,潜在的可能性|
15091517

15101518
+ 这个web要是能设计得可以闭眼(完全不睁眼)键盘控制背单词就好了。
15111519
+ 也许可以加个AI用最近词编故事功能(返回接口中支持标注所使用单词高亮?)

Solutions/Other-Japanese-LearningNotes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ xx型
234234
|仕事(しごと)|工作|
235235
|働き(はたらき)|工作|
236236
|つとめて|上班|
237+
|残業(ざんぎょう)|加班|
237238
|ならび|排队|
238239
|作り(つくり)|制作|
239240
|会い(あい)|见面|
@@ -311,6 +312,7 @@ xx型
311312
|ラーメン|拉面|
312313
|ラーメン屋(ラーメンや)|拉面店|
313314
|パスタ|意大利面|
315+
|居酒屋(いざかや)|居酒屋|
314316
|ドーナツ(doughnut)|甜甜圈|
315317
|ジュース|果汁|
316318
|牛乳(ぎゅうにゅう)|牛奶|

0 commit comments

Comments
 (0)