Every day a Leetcode
题目来源:2976. 转换字符串的最小成本 I
解法1:最短路
建图,从 original[i] 向 changed[i] 连边,边权为 cost[i]。没边的边权设为 INF。
然后用 Floyd 算法求图中任意两点最短路,得到 g 矩阵。这里得到的 g[i][j] 表示字母 i 通过若干次替换操作变成字母 j 的最小成本。
最后累加所有 g[original[i]],即为答案。如果中间遇到边权为 INF,说明无法转换,返回 −1。
代码:
/*
* @lc app=leetcode.cn id=2976 lang=cpp
*
* [2976] 转换字符串的最小成本 I
*/
// @lc code=start
class Solution
{
private:
const int INF = 1e9;
public:
long long minimumCost(string source, string target, vector<char> &original, vector<char> &changed, vector<int> &cost)
{
// 邻接矩阵
vector<vector<long long>> g(26, vector<long long>(26, INF));
// 初始化
for (int i = 0; i < 26; i++)
g[i][i] = 0;
// 建图
for (int i = 0; i < original.size(); i++)
{
int x = original[i] - 'a', y = changed[i] - 'a';
g[x][y] = min(g[x][y], (long long)cost[i]);
}
// Floyd 算法求最短路
for (int k = 0; k < 26; k++)
for (int i = 0; i < 26; i++)
for (int j = 0; j < 26; j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
// 计算最小成本
long long minCost = 0;
for (int i = 0; i < source.size(); i++)
{
int x = source[i] - 'a', y = target[i] - 'a';
if (x != y)
{
// x 不能变成 y,无解
if (g[x][y] >= INF)
return -1;
// 否则答案增加把 x 改成 y 的最小代价
minCost += g[x][y];
}
}
return minCost;
}
};
// @lc code=end
结果:
复杂度分析:
时间复杂度:O(n+m+∣Σ∣3),其中 n 为字符串 source/target 的长度,m 为数组 original/changed/cost 的长度,∣Σ∣ 为字符集合的大小,本题中字符均为小写字母,所以 ∣Σ∣=26。
空间复杂度:O(∣Σ∣2),其中 ∣Σ∣ 为字符集合的大小,本题中字符均为小写字母,所以 ∣Σ∣=26。