LeetCode 1208. 尽可能使字符串相等【不定长滑窗,字符串】1497

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。

为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库:https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。

由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。

给你两个长度相同的字符串,st

s 中的第 i 个字符变到 t 中的第 i 个字符需要 |s[i] - t[i]| 的开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。

用于变更字符串的最大预算是 maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。

如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。

如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0

示例 1:

java 复制代码
输入:s = "abcd", t = "bcdf", maxCost = 3
输出:3
解释:s 中的 "abc" 可以变为 "bcd"。开销为 3,所以最大长度为 3。

示例 2:

java 复制代码
输入:s = "abcd", t = "cdef", maxCost = 3
输出:1
解释:s 中的任一字符要想变成 t 中对应的字符,其开销都是 2。因此,最大长度为 1。

示例 3:

java 复制代码
输入:s = "abcd", t = "acde", maxCost = 0
输出:1
解释:a -> a, cost = 0,字符串未发生变化,所以最大长度为 1。

提示:

  • 1 <= s.length <= 10^5
  • t.length == s.length
  • 0 <= maxCost <= 10^6
  • st 都只含小写英文字母。

假定字符串 s s s 和 t t t 的长度均为 n n n ,对任意 0 ≤ i < n 0\le i \lt n 0≤i<n ,将 s [ i ] s[i] s[i] 变为 t [ i ] t[i] t[i] 的开销是 ∣ s [ i ] − t [ i ] ∣ | s[i] - t[i] | ∣s[i]−t[i]∣ ,由此可建立一个长度为 n n n 的数组 d i f f diff diff ,其中 d i f f [ i ] = ∣ s [ i ] − t [ i ] ∣ diff[i] = | s[i] - t[i] | diff[i]=∣s[i]−t[i]∣ 。

创建数组 d i f f diff diff 后,问题转换为计算数组 d i f f diff diff 中元素和不超过 m a x C o s t maxCost maxCost 的最长子数组长度 。用前缀和+二分查找 ,或者不定长滑窗很容易解决此题。此处用滑窗更优。

解法 不定长滑窗

由于 d i f f diff diff 的的每个元素都是非负的,因此可以用滑动窗口的方法得到符合要求的最长子数组的长度。

滑动窗口的思想是,维护两个指针 l e f t left left 和 r i g h t right right 表示数组 d i f f diff diff 的子数组的开始下标和结束下标,满足子数组的元素和不超过 m a x C o s t maxCost maxCost ,子数组的长度是 r i g h t − l e f t + 1 right−left+1 right−left+1 。初始时, l e f t left left 和 r i g h t right right 的值都是 0 0 0 。

还要维护子数组的元素和 c o s t cost cost ,初值为 0 0 0 。在移动两个指针的过程中,更新 c o s t cost cost 的值,判断子数组的元素和是否大于 m a x C o s t maxCost maxCost ,并决定应该如何移动指针。

为了得到符合要求的最长子数组的长度,应遵循以下两点原则:

  • 当 l e f t left left 的值固定时, r i g h t right right 的值应尽可能大;
  • 当 r i g h t right right 的值固定时, l e f t left left 的值应尽可能小。

基于上述原则,滑动窗口的做法如下:

  1. 将 d i f f [ r i g h t ] diff[right] diff[right] 的值加到 c o s t cost cost ;
  2. 如果 c o s t ≤ m a x C o s t cost≤maxCost cost≤maxCost ,则子数组的元素和不超过 m a x C o s t maxCost maxCost ,使用当前子数组的长度 r i g h t − l e f t + 1 right−left+1 right−left+1 更新最大子数组的长度;
  3. 如果 c o s t > m a x C o s t cost>maxCost cost>maxCost ,则子数组的元素和大于 m a x C o s t maxCost maxCost ,需要向右移动指针 l e f t left left 并同时更新 c o s t cost cost 的值,直到 c o s t ≤ m a x C o s t cost≤maxCost cost≤maxCost ,此时子数组的元素和不超过 m a x C o s t maxCost maxCost ,使用子数组的长度 r i g h t − l e f t + 1 right−left+1 right−left+1 更新最大子数组的长度;
  4. 将指针 r i g h t right right 右移一位,重复上述步骤,直到 r i g h t right right 超出数组下标范围。

遍历结束之后,即可得到符合要求的最长子数组的长度,即字符串可以转化的最大长度。

java 复制代码
class Solution {
    public int equalSubstring(String s, String t, int maxCost) {
        int n = s.length();
        int ans = 0;
        int cost = 0;
        for (int l = 0, r = 0; r < n; ++r) {
            cost += Math.abs(s.charAt(r) - t.charAt(r));
            while (cost > maxCost) {
                cost -= Math.abs(s.charAt(l) - t.charAt(l));
                ++l;
            }
            ans = Math.max(ans, r - l + 1);
        }
        return ans;
    }
}

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)
相关推荐
FakeOccupational2 小时前
【数学 密码学】量子通信:光的偏振&极化的量子不确定性特性 + 量子密钥分发 BB84算法步骤
算法·密码学
ZhengEnCi3 小时前
S10-蓝桥杯 17822 乐乐的积木塔
算法
贾斯汀玛尔斯3 小时前
每天学一个算法--拓扑排序(Topological Sort)
算法·深度优先
大龄程序员狗哥4 小时前
第25篇:Q-Learning算法解析——强化学习中的经典“价值”学习(原理解析)
人工智能·学习·算法
exp_add34 小时前
质数相关知识
算法
小辉同志4 小时前
215. 数组中的第K个最大元素
数据结构·算法·leetcode··快速选择
小O的算法实验室5 小时前
2025年IEEE TITS,基于矩阵的进化计算+面向无线传感器网络数据收集无人机路径规划,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
OidEncoder5 小时前
编码器分辨率与机械精度的关系
人工智能·算法·机器人·自动化
memcpy05 小时前
LeetCode 2615. 等值距离和【相同元素分组+前缀和;考虑距离和的增量】中等
算法·leetcode·职场和发展
炽烈小老头6 小时前
【 每天学习一点算法 2026/04/22】四数相加 II
学习·算法