Q1题目链接:https://leetcode.com/problems/valid-palindrome-ii/
leetcode 680
看到题目的第一思路:
和之前做的125题类似 都是用双指针方法判断字符串是否回文
但是解题思路略有差异
代码随想录之后的想法和总结:
正确的解题思路:
第一步:正常双指针往中间走
如果:s[left] == s[right] 那就很简单:
left++
right--
继续。
第二步:什么时候才动用“删除一次”的机会?
只有在:s[left] != s[right]
的时候。
这时你不能随便继续走,也不能直接 false。
你要问:如果删掉左边这个字符,剩下的是不是回文?
或者如果删掉右边这个字符,剩下的是不是回文?
第三步:为什么要分成两种尝试?
因为你第一次不匹配时,不知道问题出在:
左边这个字符多余
还是右边这个字符多余
例如:abca
当走到b和c时不相等,
你要分别想:
跳过
b,看"aca"是不是回文跳过
c,看"aba"是不是回文
只要有一种成立,就返回true。
时间复杂度以及空间复杂度:
时间复杂度:O(n)
原因:
主循环走一遍
最多调用一次子函数(也是 O(n))
Q2题目链接:https://leetcode.com/problems/reverse-string/
leetcode #344
看到题目的第一思路:
双指针
代码随想录之后的想法和总结:
注意原地交换:
交换的关键永远是:先保存一边的旧值
通常保存左边更自然:
temp = 左边 左边 = 右边 右边 = temp
时间复杂度以及空间复杂度:
Q3题目链接:https://leetcode.com/problems/reverse-words-in-a-string/
leetcode #151
看到题目的第一思路:
这个问题虽然也是用双指针,但是不是之前的题目那样的左右夹击双指针,
反而是一种同向 / 扫描双指针
大概思路:从右往左扫描字符串,每次找到一个完整单词,按找到的顺序拼到结果里。
代码随想录之后的想法和总结:
难点:
1怎么跳过多余空格
2怎么确定一个单词的左右边界
比如从右往左扫描时,遇到d开始,怎么知道world整个单词在哪里结束、从哪里开始?
这就会用到“指针移动”。需要用双指针来记录两个位置:
比如:i:用来扫描,当找到单词尾部时,记一个j
思路像这样:
i 从右往左走 先跳过空格 如果 i < 0,结束 j = i // j 先记住当前单词末尾 然后继续往左走,直到遇到空格 这时单词范围就是 [i+1 ... j]
这个区间就是一个完整单词。
完整的解题思路:
从右往左扫描
跳过空格
记录单词结尾
j往左找到单词开头
用
substring(i+1, j+1)取出单词用
StringBuilder拼结果中间只加一个空格
时间复杂度以及空间复杂度:
今日收获,学习时长:
第一题:
注意这里用到了两个双指针循环
因此:观察一下他们的区别:
主循环:允许犯一次错误(可以删一个字符)
子循环:不允许犯错(必须严格回文)
| 逻辑 | 是否允许出错 | 行为 |
|---|---|---|
| 主循环 | ✅ 允许一次 | 不等 → 尝试删除 |
| 子循环 | ❌ 不允许 | 不等 → 直接 false |
第二题:数据类型不同 语法不同 为什么会混乱?
因为你做的题:
125 / 680 →
String344 →
char[]
👉逻辑一样(双指针)
👉但数据类型不同 → 访问方式不同
判断方法(考试/面试用)
你只需要看函数参数:
👉 如果是这样:
public boolean isPalindrome(String s) ✔ 用:s.charAt(i)
👉 如果是这样:
public void reverseString(char[] s) ✔ 用:s[i]