1208. 尽可能使字符串相等
难度中等58
给你两个长度相同的字符串,s
和 t
。
将 s
中的第 i
个字符变到 t
中的第 i
个字符需要 |s[i] - t[i]|
的开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。
用于变更字符串的最大预算是 maxCost
。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。
如果你可以将 s
的子字符串转化为它在 t
中对应的子字符串,则返回可以转化的最大长度。
如果 s
中没有子字符串可以转化成 t
中对应的子字符串,则返回 0
。
二分方法
func abs(a int) int {
if a > 0 {
return a
}
return -a
}
//二分搜索加滑窗
func equalSubstringBinary(s string, t string, maxCost int) int {
left, right, best := 0, len(s), 0
for left <= right {
mid := (left-right)/2 + right
if judge(s, t, maxCost, mid) {
best, left = mid, mid+1
} else {
right = mid - 1
}
}
return best
}
func judge(s string, t string, maxCost int, winLen int) bool {
winSum := 0
for i := 0; i < winLen; i++ {
winSum += abs(int(s[i]) - int(t[i]))
}
if winSum <= maxCost {
return true
}
for i := winLen; i < len(s); i++ {
winSum -= abs(int(s[i-winLen]) - int(t[i-winLen]))
winSum += abs(int(s[i]) - int(t[i]))
if winSum <= maxCost {
return true
}
}
return false
}
直接滑窗
//纯滑窗
func equalSubstring(s string, t string, maxCost int) int {
tmpCost, maxLen := 0, 0
beg, end := 0, 0 //左闭,右开区间
//注意这里 条件是 beg<= end,beg也可以等于end,意味着从新开始新的区间. 例如s和t中相应字符的差值 都大于 maxCost 的情况
for beg <= end && end < len(s) {
if tmpCost <= maxCost { //当前窗口可以满足预算
if end-beg > maxLen {
maxLen = end - beg
}
//然后追加 end
delTa := abs(int(s[end]) - int(t[end]))
tmpCost += delTa
end++
continue
}
//去掉beg
delTa := abs(int(s[beg]) - int(t[beg]))
tmpCost -= delTa
beg++
}
//这里不能漏掉,要再次判断下
if tmpCost <= maxCost && (end-beg) > maxLen {
maxLen = end - beg
}
return maxLen
}
func abs(a int) int {
if a > 0 {
return a
}
return -a
}