Leetcode 3389. Minimum Operations to Make Character Frequencies Equal

  • [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个所需的最小操作次数。

而这个又是可以通过动态规划来进行实现,只不过每一个值都需要考虑以下几种情况:

  1. 当前值变为 0 0 0,下一个值变为 k k k
  2. 当前值变为 0 0 0,下一个值也变为 0 0 0
  3. 当前值变为 k k k,下一个值变为 0 0 0
  4. 当前值变为 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。

相关推荐
少许极端1 天前
算法奇妙屋(二十四)-二维费用的背包问题、似包非包问题、卡特兰数问题(动态规划)
算法·动态规划·卡特兰数·二维费用背包·似包非包
闻缺陷则喜何志丹1 天前
【状态机动态规划】3686. 稳定子序列的数量|1969
c++·算法·动态规划·力扣·状态机动态规划
少许极端1 天前
算法奇妙屋(二十三)-完全背包问题(动态规划)
java·算法·动态规划·完全背包
星马梦缘2 天前
算法与数据结构
数据结构·c++·算法·动态规划·克鲁斯卡尔·kahn
Snow_day.2 天前
有关排列排列组合(1)
数据结构·算法·贪心算法·动态规划·图论
Tisfy2 天前
LeetCode 0712.两个字符串的最小ASCII删除和:反向思维保留最大(动态规划)
算法·leetcode·动态规划·字符串·dp·子序列
鲨莎分不晴3 天前
反向传播的数学本质:链式法则与动态规划的完美共舞
算法·动态规划
老鼠只爱大米3 天前
LeetCode算法题详解 42:接雨水
leetcode·动态规划·双指针·单调栈·接雨水·雨水收集
闻缺陷则喜何志丹3 天前
【C++动态规划 状压dp】1879. 两个数组最小的异或值之和|2145
c++·算法·动态规划·力扣·数组·最小·动态规范