题目描述
思路解析动画文字版
记住三件事:相等就往里收;第一次撞到不等时,分别试「删左」和「删右」;两条岔路有一条通,答案就是 true。下面每一帧都在套它。
开始:左指针 l 停在下标 0,右指针 r 停在最后一格。删除名额还留着,先按普通回文那样一对一对地比。
左边 'a' 和右边 'a' 一样,这一对配上了,可以放心往里收。
l 前进到下标 1、r 后退到下标 9,继续比下一对(绿色是已经确认相等的部分)。
左边 'b' 和右边 'b' 一样,这一对配上了,可以放心往里收。
l 前进到下标 2、r 后退到下标 8,继续比下一对(绿色是已经确认相等的部分)。
左边 'c' 和右边 'c' 一样,这一对配上了,可以放心往里收。
l 前进到下标 3、r 后退到下标 7,继续比下一对(绿色是已经确认相等的部分)。
左边 'd' 和右边 'd' 一样,这一对配上了,可以放心往里收。
l 前进到下标 4、r 后退到下标 6,继续比下一对(绿色是已经确认相等的部分)。
撞上了:左边 'e' 和右边 'x' 对不上(标红)。普通回文到这就失败了,但我们还有一次删除机会,下面分两条岔路试。
岔路一:假设删掉左边那个 'e'(标灰表示当它不存在),那么要比的就变成「下标 5 到 6」这一段,看它本身是不是回文。
删左这条路在 'e' 与 'x' 上又对不上了(这次没有删除名额可用了),所以「删左」走不通。
岔路二:换一种删法,假设删掉右边那个 'x'(标灰当它不存在),要比的就变成「下标 4 到 5」这一段,再看它是不是回文。
删右这条路上,'e' 和 'e' 相等,这一对配上了。
删右这段的指针交错而过,一路都相等。
删右这条路一路对上,剩下的部分是回文,删右可行——只要有一条岔路通,整体答案就成立。
结论:删掉那个对不上的 'x',剩下的字符正读倒读完全一样,所以答案是 true。一次删除机会刚好用在了刀刃上。
三个边界:本就是回文、串太短、以及删一个也救不回——分别对应不进岔路、直接返回、两路皆败。
三个高频追问:为何只用一次机会、分支内为何不能再删、以及推广到删 k 个时要换 DP。
参考代码
def validPalindrome(s): def isPal(i, j): # 普通回文判断 while i < j: if s[i] != s[j]: return False i += 1; j -= 1 return True l, r = 0, len(s) - 1 while l < r: if s[l] != s[r]: # 撞到不等:用掉删除名额 return isPal(l + 1, r) or isPal(l, r - 1) l += 1; r -= 1 return True复杂度
- 时间:O(n),主扫描最多走半趟;撞到不等后两个分支各最多再走半趟,合起来仍是线性
- 空间:O(1),只用 l、r 两个下标,不额外开数组(递归/切片版本可能多花空间,这里用下标避免)
易错点
面试追问把动画讲成自己的话
追问为什么撞到不等时,只需要用一次删除机会、不用递归地继续允许删除?
追问分支里的 isPal 为什么不再允许删字符?
追问如果改成『最多删 k 个字符』,这套思路还能直接用吗?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
计数二进制子串
LeetCode 696 · 简单 · 沿着 双指针套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题