Leetcode 2977. Minimum Cost to Convert String II

1. 解题思路

这一题思路上和前一题差不多,还是先对给定的有向图求出其中任意两点间的最短距离,然后考察字符串的变换方式。

但是,这里相较于上一题的难度在于说,这里的有向图的变换节点不再单纯是字母了,因此组合更多了。

其次的话,由于变换的节点为不定长的字符串,因此对source字符串和target字符串的变换关系可以给出不同的拆分关系,可以有不同的cost,需要对其选择最小值。

但是,即便如此,思路上来说还是很直接的,上半部分本质上和上一题一模一样,用一个Floyd算法就能直接得到。

而关于后半部分,事实上更加简单,直接使用动态规划就行。

不过,实际在处理过程中,遇到了超时的问题,因此这里做了一些剪枝的优化操作,这部分还是比较零碎的:

  1. Floyd算法的算法复杂度是 O ( N 3 ) O(N^3) O(N3),因此我们需要对所有的节点进行一下去重,并且对第一层的节点提前求出了所有可能的中间节点的可能性,从而进一步进行了剪枝;
  2. 对于动态规划的部分,我们引入了一个trie树,使得遍历过程可以提前终止,将整体的算法复杂度从 O ( N 2 ) O(N^2) O(N2)大幅进行缩减。

但即便给出上述这些多少繁琐的剪枝操作,还是仅仅勉强通过了所有测试样例,耗时依然非常长,不知道其他大佬们是怎么处理的,看了一两个大佬们的解法,不过没有看懂就是了,唉……

2. 代码实现

给出python代码实现如下:

class Trie:
    def __init__(self):
        self.trie = {
   }
    
    def add_word(self, word):
        trie = self.trie
        for c in word:
            trie = trie.setdefault(c, {
   })
        trie["eos"] = ""

class Solution:
    def minimumCost(self, source: str, target: str, original: List[str], changed: List[str], cost: List[int]) -> int:
        n, m = len(source), len(original)
        
        costs = defaultdict(lambda: math.inf)
        for src, tgt, c in zip(original, changed, cost):
            costs[(src, tgt)] = min(c, costs[(src, tgt)])
        original = list(set(original))
        changed_set = set(changed)
        changed = list(changed_set)
        interval = [src for src in original if src in changed_set]
        for mid in interval:
            for src in original:
                for tgt in changed:
                    costs[(src, tgt)] = min(costs[(src, tgt)], costs[(src, mid)] + costs[(mid, tgt)])
        
        trie = Trie()
        for src in original:
            trie.add_word(src)

        @lru_cache(None)
        def dp(idx):
            if idx >= n:
                return 0
            ans = math.inf
            _trie = trie.trie
            src, tgt = "", ""
            for j in range(idx, n):
                src, tgt = src + source[j], tgt + target[j]
                if src == tgt:
                    ans = min(ans, dp(j+1))
                elif (src, tgt) in costs:
                    ans = min(ans, costs[(src, tgt)] + dp(j+1))
                if source[j] not in _trie:
                    break
                _trie = _trie[source[j]]
            return ans
        
        ans = dp(0)
        return ans if ans != math.inf else -1

提交代码评测得到:耗时16432ms,占用内存30.3MB。

相关推荐

  1. Leetcode 2977. Minimum Cost to Convert String II

    2023-12-25 06:28:05       67 阅读
  2. LeetCode 2974. 最小数字游戏

    2023-12-25 06:28:05       61 阅读
  3. Leetcode 297. Serialize and Deserialize Binary Tree

    2023-12-25 06:28:05       29 阅读
  4. Leetcode 2976. Minimum Cost to Convert String I

    2023-12-25 06:28:05       65 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-25 06:28:05       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-25 06:28:05       106 阅读
  3. 在Django里面运行非项目文件

    2023-12-25 06:28:05       87 阅读
  4. Python语言-面向对象

    2023-12-25 06:28:05       96 阅读

热门阅读

  1. 算法练习Day21 (Leetcode/Python-回溯算法)

    2023-12-25 06:28:05       62 阅读
  2. 简单二分查找(C++算法)

    2023-12-25 06:28:05       65 阅读
  3. LeetCode 2703. 返回传递的参数的长度

    2023-12-25 06:28:05       54 阅读
  4. 前端---初始常用的 html 标签

    2023-12-25 06:28:05       65 阅读
  5. List 流的使用

    2023-12-25 06:28:05       52 阅读
  6. 【Python】Python 批量转换PDF到Excel

    2023-12-25 06:28:05       55 阅读
  7. UE 动画系统框架介绍及使用

    2023-12-25 06:28:05       59 阅读
  8. python入门实战经典15题

    2023-12-25 06:28:05       47 阅读
  9. SpringBoot Gateway整合过程中的问题

    2023-12-25 06:28:05       78 阅读