- [Leetcode 3389. Minimum Operations to Make Character Frequencies Equal](#Leetcode 3389. Minimum Operations to Make Character Frequencies Equal)
- [1. 解题思路](#1. 解题思路)
- [2. 代码实现](#2. 代码实现)
1. 解题思路
这一题从答题从test的结果来说来说做出的人很少,主要确实有些繁琐,因为还是那种分类讨论的问题,然后思路上也比较暴力。
这道题我自己也没有完全自力搞定,因为一开始觉得不会这么暴力,然后就没怎么找到思路,结果看了一下大佬们的回答之后发现核心思路其实差不多,只不过我觉得铁定超时就没有往下去尝试,然后大佬做了,然后就过了......
这道题思路上如前所述,非常的暴力,就是遍历所有可能的最终值情况下各自需要多少操作,然后取最小值。
因此,这里的核心问题就变成了,给定一个最终值 k k k,如何计算将原始字符串变换为最终所有的字符都为 k k k个所需的最小操作次数。
而这个又是可以通过动态规划来进行实现,只不过每一个值都需要考虑以下几种情况:
- 当前值变为 0 0 0,下一个值变为 k k k
- 当前值变为 0 0 0,下一个值也变为 0 0 0
- 当前值变为 k k k,下一个值变为 0 0 0
- 当前值变为 k k k,下一个值也变为 k k k
另外,如果当前值如果需要减少现有值的情况下,需要考察下一个值是否需要增加值,如果需要的话需要使用操作3来进行操作复用。
可以看到,这个逻辑还是蛮复杂的,需要一些分类讨论,但整体理清楚了思路就整体还是挺直接的了。
2. 代码实现
我们给出最终的python代码实现如下:
python
class Solution:
def makeStringGood(self, s: str) -> int:
cnt = Counter(s)
@lru_cache(None)
def count_op(tgt):
nums = [cnt[ch] for ch in string.ascii_lowercase]
@lru_cache(None)
def dfs(idx, nxt):
if idx == 25:
current = nums[idx] + nxt
return min(current, abs(tgt-current))
ans = math.inf
current = nums[idx] + nxt
nxt = nums[idx+1]
if current == 0 or current == tgt:
return dfs(idx+1, 0)
if nxt == 0 or nxt >= tgt:
ans = min(ans, min(current, abs(current-tgt)) + dfs(idx+1, 0))
elif current > tgt:
ans = min(
ans,
current-tgt + dfs(idx+1, 0),
current-tgt + dfs(idx+1, min(tgt-nxt, current-tgt))
)
else:
ans = min(
ans,
tgt-current + dfs(idx+1, 0),
current + dfs(idx+1, 0),
current + dfs(idx+1, min(tgt-nxt, current))
)
return ans
ans = dfs(0, 0)
return ans
ans = min(count_op(i) for i in range(1, max(cnt.values())+1))
return ans
提交代码评测得到:耗时1115ms,占用内存19.8MB。