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 be6d637

Browse files
author
robot
committed
feat: 3347ドル
1 parent 783bc5c commit be6d637

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
2+
## 题目地址(3347. 执行操作后元素的最高频率 II - 力扣(LeetCode))
3+
4+
https://leetcode.cn/problems/maximum-frequency-of-an-element-after-performing-operations-ii/description/
5+
6+
## 题目描述
7+
8+
<p>给你一个整数数组&nbsp;<code>nums</code>&nbsp;和两个整数&nbsp;<code>k</code> 和&nbsp;<code>numOperations</code>&nbsp;。</p>
9+
10+
<p>你必须对 <code>nums</code>&nbsp;执行 <strong>操作</strong>&nbsp; <code>numOperations</code>&nbsp;次。每次操作中,你可以:</p>
11+
12+
<ul>
13+
<li>选择一个下标&nbsp;<code>i</code>&nbsp;,它在之前的操作中 <strong>没有</strong>&nbsp;被选择过。</li>
14+
<li>将 <code>nums[i]</code>&nbsp;增加范围&nbsp;<code>[-k, k]</code>&nbsp;中的一个整数。</li>
15+
</ul>
16+
17+
<p>在执行完所有操作以后,请你返回 <code>nums</code>&nbsp;中出现 <strong>频率最高</strong>&nbsp;元素的出现次数。</p>
18+
19+
<p>一个元素 <code>x</code>&nbsp;的 <strong>频率</strong>&nbsp;指的是它在数组中出现的次数。</p>
20+
21+
<p>&nbsp;</p>
22+
23+
<p><strong class="example">示例 1:</strong></p>
24+
25+
<div class="example-block">
26+
<p><span class="example-io"><b>输入:</b>nums = [1,4,5], k = 1, numOperations = 2</span></p>
27+
28+
<p><span class="example-io"><b>输出:</b>2</span></p>
29+
30+
<p><strong>解释:</strong></p>
31+
32+
<p>通过以下操作得到最高频率 2 :</p>
33+
34+
<ul>
35+
<li>将&nbsp;<code>nums[1]</code>&nbsp;增加 0 ,<code>nums</code> 变为&nbsp;<code>[1, 4, 5]</code>&nbsp;。</li>
36+
<li>将&nbsp;<code>nums[2]</code>&nbsp;增加 -1 ,<code>nums</code> 变为&nbsp;<code>[1, 4, 4]</code>&nbsp;。</li>
37+
</ul>
38+
</div>
39+
40+
<p><strong class="example">示例 2:</strong></p>
41+
42+
<div class="example-block">
43+
<p><span class="example-io"><b>输入:</b>nums = [5,11,20,20], k = 5, numOperations = 1</span></p>
44+
45+
<p><span class="example-io"><b>输出:</b>2</span></p>
46+
47+
<p><strong>解释:</strong></p>
48+
49+
<p>通过以下操作得到最高频率 2 :</p>
50+
51+
<ul>
52+
<li>将&nbsp;<code>nums[1]</code>&nbsp;增加 0 。</li>
53+
</ul>
54+
</div>
55+
56+
<p>&nbsp;</p>
57+
58+
<p><strong>提示:</strong></p>
59+
60+
<ul>
61+
<li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li>
62+
<li><code>1 &lt;= nums[i] &lt;= 10<sup>9</sup></code></li>
63+
<li><code>0 &lt;= k &lt;= 10<sup>9</sup></code></li>
64+
<li><code>0 &lt;= numOperations &lt;= nums.length</code></li>
65+
</ul>
66+
67+
## 前置知识
68+
69+
- 二分
70+
71+
## 公司
72+
73+
- 暂无
74+
75+
## 思路
76+
77+
容易想到的是枚举最高频率的元素的值 v。v 一定是介于数组的最小值 - k 和最大值 + k 之间的。因此我们可以枚举所有可能得值。但这会超时。可以不枚举这么多么?答案是可以的。
78+
79+
刚开始认为 v 的取值一定是 nums 中的元素值中的一个,因此直接枚举 nums 即可。但实际上是不对的。比如 nums = [88, 53] k = 27 变为 88 或者 53 最高频率都是 1,而变为 88 - 27 = 61 则可以使得最高频率变为 2。
80+
81+
那 v 的取值有多少呢?实际上除了 nums 的元素值,还需要考虑 nums[i] + k, nums[i] - k。为什么呢?
82+
83+
数形结合更容易理解。
84+
85+
如下图,黑色点表示 nums 中的元素值,它可以变成的值的范围用竖线来表示。
86+
87+
![](https://p.ipic.vip/l6zg9z.png)
88+
89+
如果两个之间有如图红色部分的重叠区域,那么就可以通过一次操作使得二者相等。当然如果两者本身就相等,就不需要操作。
90+
91+
![](https://p.ipic.vip/e6pjxd.png)
92+
93+
如上图,我们可以将其中一个数变成另外一个数。但是如果两者是下面的关系,那么就不能这么做,而是需要变为红色部分的区域才行。
94+
95+
![](https://p.ipic.vip/9xgdx1.png)
96+
97+
如果更进一步两者没有相交的红色区域,那么就无法通过操作使得二者相等。
98+
99+
![](https://p.ipic.vip/0k19iy.png)
100+
101+
最开始那种朴素的枚举,我们可以把它看成是一个红线不断在上下移动,不妨考虑从低往高移动。
102+
103+
那么我们可以发现红线只有移动到 nums[i], nums[i] + k, nums[i] - k 时,才会突变。这个突变指的是可以通过操作使得频率变成多大的值会发生变化。也就是说,我们只需要考虑 nums[i], nums[i] + k, nums[i] - k 这三个值即可,而不是这之间的所有值。
104+
105+
![](https://p.ipic.vip/hermvm.png)
106+
107+
理解了上面的过程,最后只剩下一个问题。那就是对于每一个 v。找 满足 nums[i] - k <= v <= nums[i] + k 的有几个,我们就能操作几次,频率就能多多少(不考虑 numOperations 影响),当然要注意如果 v == nums[i] 就不需要操作。
108+
109+
110+
具体来说:
111+
112+
- 如果 nums[i] == v 不需要操作。
113+
- 如果 nums[i] - k <= v <= nums[i] + k,操作一次
114+
- 否则,无法操作
115+
116+
找 nums 中范围在某一个区间的个数如何做呢?我们可以使用二分查找。我们可以将 nums 排序,然后使用二分查找找到 nums 中第一个大于等于 v - k 的位置,和第一个大于 v + k 的位置,这两个位置之间的元素个数就是我们要找的。
117+
118+
最后一个小细节需要注意,能通过操作使得频率增加的量不能超过 numOperations。
119+
120+
## 关键点
121+
122+
- 枚举 nums 中的元素值 num 和 num + k, num - k 作为最高频率的元素的值 v
123+
124+
## 代码
125+
126+
- 语言支持:Python3
127+
128+
Python3 Code:
129+
130+
```python
131+
class Solution:
132+
def maxFrequency(self, nums: List[int], k: int, numOperations: int) -> int:
133+
# 把所有要考虑的值放进 set 里
134+
st = set()
135+
# 统计 nums 里每种数出现了几次
136+
mp = Counter(nums)
137+
for x in nums:
138+
st.add(x)
139+
st.add(x - k)
140+
st.add(x + k)
141+
142+
# 给 nums 排序,方便接下来二分计数。
143+
nums.sort()
144+
ans = 0
145+
for x in st:
146+
except_self = (
147+
bisect.bisect_right(nums, x + k)
148+
- bisect.bisect_left(nums, x - k)
149+
- mp[x]
150+
)
151+
ans = max(ans, mp[x] + min(except_self, numOperations))
152+
return ans
153+
154+
155+
156+
```
157+
158+
159+
**复杂度分析**
160+
161+
令 n 为数组长度。
162+
163+
- 时间复杂度:$O(nlogn)$
164+
- 空间复杂度:$O(n)$
165+
166+
167+
168+
169+
> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
170+
171+
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~
172+
173+
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 54K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
174+
175+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
176+
177+
![](https://p.ipic.vip/h9nm77.jpg)

0 commit comments

Comments
(0)

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