Leetcode-3361两个字符串的切换距离

发布于:2025-07-30 ⋅ 阅读:(17) ⋅ 点赞:(0)

依旧前缀和,这题本来应该是昨天做的,没做出来,一直拖到今天,看了题解几次三番,总算是自己写了出来,心态炸了。

链接如下 3361. 两个字符串的切换距离

以下是做这道题的经过

没有尝试用暴力的做法。题目主要围绕两个前缀和数组的构建以及计算时的一些细节。

最开始做的尝试是在环形数组的基础上,讨论s[i]和t[i]的大小,然后减来减去,三元表达式写了很多,密密麻麻的,把我自己也给绕进去了,其实仔细写感觉应该也是能写出来?就是会有点太复杂了,脑袋大。

后来看了灵神的题解,把环形数组的元素重复了一次,相当与把数组复制了一遍,长度扩大一倍,化曲为直了,简化了问题。

前缀和数组nextCnt[53],prevCnt[53],这里假定大家都有前缀和的基础,过多的我不赘述,我也不会讲,可以参照灵神在303这道题的题解来辅助理解303. 区域和检索 - 数组不可变 - 力扣(LeetCode)

按照上面提到的的思路,构建完前缀和数组后来讨论如何计算,主要是根据s[i]和t[i]的大小来判断,我们可以简化一下s[i]和t[i],因为从题目知道s[i]是需要被改变的字符,t[i]是目标字符,s[i].t[i] ∈[a-z]所以我们可以记 int from = s[i]-'a' , to = t[i]-'a';来表示字符的序号,方便表示。

对于s中的每个字符s[i],我们需要比较他通过向前走或者向后走变为t[i]的最小花费,局部最优来达到全局最优,所以需要比较对应的前缀和prev和next。

前缀和数组是左闭右开的,所以next减去只需next[to>from?to:to+26]-next[from],

而对于prev虽然也是左闭右开的,但因为方向的问题prev[to>from?from+27:from]-prev[to+!],为什么+1画个图会更方便理解一下。

总结一下,主要做了两件事,一个是将数组复制一下,避免了环形数组讨论麻烦,另一个是将s[i]和t[i]简化为from和to,便于去判断。

C++代码如下:

class Solution {
public:
    long long shiftDistance(string s, string t, vector<int>& nextCost,
                            vector<int>& previousCost) {
        int cNum = 26;
        long long nextcnt[53]{}, precnt[53]{};
        for (int i = 0; i < 52; i++) {
            nextcnt[i + 1] = nextcnt[i] + nextCost[i % 26];
            precnt[i + 1] = precnt[i] + previousCost[i % 26];
        }
        long long ans = 0;
        for (int i = 0; i < s.length(); i++) {
            int from = s[i] - 'a';
            int to = t[i] - 'a';
            ans += min((from > to ? nextcnt[to + 26] - nextcnt[from]
                                  : nextcnt[to] - nextcnt[from]),
                       (from > to ? precnt[from + 1] - precnt[to + 1]
                                  : precnt[from + 27] - precnt[to + 1]));
        }
        return ans;
    }
};


网站公告

今日签到

点亮在社区的每一天
去签到