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

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

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

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

给你两个长度相同的字符串,s 和 t。

将 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
  • s 和 t 都只含小写英文字母。

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

创建数组 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 diffright diffright 的值加到 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)
相关推荐
mmmmath_315 分钟前
LeetCode.104.二叉树的最大深度
数据结构·leetcode
YangYang9YangYan1 小时前
2027供应链计划校招:数学与应用数学专业如何把预测模型讲成业务决策?
人工智能·sql·算法
jsjzsl21 小时前
递归自改进系统(RSI)的本质是自发对称破缺:智能爆炸有界—— AI研发切记盲目投入
人工智能·python·算法
程序员清风1 小时前
最短路径算法:BFS、Dijkstra 与 Floyd
java·算法·宽度优先
梦帮科技1 小时前
Kali Linux Scapy 畸形报文构造学——深度解剖非法 TCP Flags 与反常序列号
linux·爬虫·神经网络·算法·数学建模·系统架构·模拟退火算法
171320330计算机毕设编程3 小时前
计算机毕业设计 基于YOLO改进算法的车辆特征识别系统设计与实现--lw
java·大数据·python·sql·算法
姜鱼问生3 小时前
Nginx gzip 压缩:一个配置让页面加载快 3 倍
后端·算法·架构
不会就选b3 小时前
算法日常・每日刷题--<动态规划>23
算法·动态规划
GreatSQL社区3 小时前
主从复制SQL线程中断——字符集砸出的坑
java·数据库·算法