LeetCode1208. 儘可能使字串相等(滑動視窗)
阿新 • • 發佈:2021-02-06
1、題目描述
https://leetcode-cn.com/problems/get-equal-substrings-within-budget/
給你兩個長度相同的字串,s 和 t。只含小寫英文字母。
- 將 s中的第i個字元變到t中的第 i 個字元需要|s[i] - t[i]|的開銷(開銷可能為 0),也就是兩個字元的 ASCII 碼值的差的絕對值。
- 用於變更字串的最大預算是maxCost。在轉化字串時,總開銷應當小於等於該預算,這也意味著字串的轉化可能是不完全的。
如果你可以將 s 的子字串轉化為它在 t 中對應的子字串,則返回可以轉化的最大長度。
如果 s 中沒有子字串可以轉化成 t 中對應的子字串,則返回 0。
輸入:s = "abcd", t = "bcdf", cost = 3
輸出:3
解釋:s 中的 "abc" 可以變為 "bcd"。開銷為 3,所以最大長度為 3。
輸入:s = "abcd", t = "cdef", cost = 3
輸出:1
解釋:s 中的任一字元要想變成 t 中對應的字元,其開銷都是 2。因此,最大長度為 1。
輸入:s = "abcd", t = "acde", cost = 0 輸出:1 解釋:你無法作出任何改動,所以最大長度為 1。
2、程式碼詳解
滑動視窗移動的思路:
- 以右指標作為驅動,拖著左指標向前走。右指標每次只移動一步,而左指標在內部 while 迴圈中每次可能移動多步。
- 右指標是主動前移,探索未知的新區域;左指標是被迫移動,負責尋找滿足題意的區間。
模板修改之處:
- 模板中的 sums需要根據題目意思具體去修改,本題是求和題目因此把sums 定義成整數用於求和;如果是計數題目,就需要改成字典用於計數。當左右指標發生變化的時候,都需要更新 sums。
- 需要根據題目去修改的是內層 while 迴圈的判斷條件,即: 區間[left, right]不符合題意 。對於本題而言,就是該區內的和 sums超過了 maxCost。
def findSubArray(nums):
N = len(nums) # 陣列/字串長度
left, right = 0, 0 # 雙指標,表示當前遍歷的區間[left, right],閉區間
sums = 0 # 用於統計 子陣列/子區間 是否有效,根據題目可能會改成求和/計數
res = 0 # 儲存最大的滿足題目要求的 子陣列/子串 長度
while right < N: # 當右邊的指標沒有搜尋到 陣列/字串 的結尾
sums += nums[right] # 增加當前右邊指標的數字/字元的求和/計數
while 區間[left, right]不符合題意:# 此時需要一直移動左指標,直至找到一個符合題意的區間
sums -= nums[left] # 移動左指標前需要從counter中減少left位置字元的求和/計數
left += 1 # 真正的移動左指標,注意不能跟上面一行程式碼寫反
# 到 while 結束時,我們找到了一個符合題意要求的 子陣列/子串
res = max(res, right - left + 1) # 需要更新結果
right += 1 # 移動右指標,去探索新的區間
return res
程式碼如下:
class Solution:
def equalSubstring(self, s: str, t: str, maxCost: int) -> int:
n = len(s)
costs = [0] * n
for i in range(n):
costs[i] = abs(ord(s[i]) - ord(t[i]))
left = 0
right = 0
sums = 0 # 用於統計 子陣列/子區間 是否有效
res = 0 # 儲存最大的滿足題目要求的 子陣列/子串 長度
while right < n:
sums += costs[right]
while sums > maxCost:
sums -= costs[left]
left += 1
res = max(res, right - left + 1)
right += 1
return res