151
社区成员
发帖
与我相关
我的任务
分享在C语言字符串笔试中,「回文串校验」是高频考点,而「允许删除一个字符」的进阶版本,更是区分普通解法和最优解法的分水岭。很多同学会用暴力枚举删除位置的方式解题,结果要么超时,要么写得复杂臃肿。今天用双指针+贪心思想,讲透这道题的最优解法和底层逻辑。
一、题目背景与核心难点
给定一个字符串,你最多可以删除其中一个字符,判断它是否能成为回文字符串。
核心难点:
- 暴力枚举删除每个字符再校验回文,时间复杂度O(n²),大数据量直接超时
- 如何高效处理「删除左字符」和「删除右字符」两种情况,不重复冗余代码
- 边界条件处理:字符串长度为1、空串、删除后剩余字符串的校验
二、核心解题思路:双指针+贪心校验
1. 相向双指针遍历:左指针从开头,右指针从末尾,向中间移动,匹配对应位置的字符。
2. 不匹配时的贪心处理:当左右字符不匹配时,有两种选择:- 方案1:删除左指针字符,校验 [l+1, r] 区间是否为回文
- 方案2:删除右指针字符,校验 [l, r-1] 区间是否为回文
只要其中一种方案校验通过,就说明原字符串可以通过删除一个字符成为回文。
3. 提前终止优化:只要有一条路径校验成功,直接返回结果,无需遍历剩余字符。
三、C语言完整可运行代码实现
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
// 辅助函数:校验指定区间[l, r]是否为回文串
bool isPalindrome(const char *s, int l, int r) {
while (l < r) {
if (s[l] != s[r]) {
return false;
}
l++;
r--;
}
return true;
}
bool validPalindrome(const char *s) {
int len = strlen(s);
int l = 0, r = len - 1;
while (l < r) {
if (s[l] != s[r]) {
// 不匹配时,尝试删除左或右字符,只要一种情况成立即可
return isPalindrome(s, l + 1, r) || isPalindrome(s, l, r - 1);
}
l++;
r--;
}
// 遍历完成都匹配,本身就是回文串
return true;
}
int main() {
printf("%d\n", validPalindrome("aba")); // 1(true)
printf("%d\n", validPalindrome("abca")); // 1(true)
printf("%d\n", validPalindrome("abc")); // 0(false)
return 0;
}
四、易错难点深度剖析
1. 不要暴力枚举删除位置
很多同学会循环遍历每个字符,删除后复制字符串再校验回文,这种方法时间复杂度O(n²),遇到长字符串会超时,而双指针解法是O(n)时间复杂度,效率提升巨大。
2. 辅助函数复用逻辑
把区间回文校验封装成辅助函数,避免重复写代码,也方便后续扩展(比如允许删除2个字符时,只需修改辅助函数调用逻辑)。
3. 边界条件处理
字符串长度为1时,直接返回true;空串也默认合法,代码中 while(l < r) 循环会自动处理这些情况,无需额外特判。
4. 短路逻辑的妙用
return A || B 的短路特性,当 isPalindrome(s, l+1, r) 为true时,不会再执行后面的 isPalindrome(s, l, r-1) ,节省不必要的校验时间。
五、算法学习总结
这道题的核心是贪心思想:遇到不匹配时,优先尝试两种可能的删除方案,只要有一条路径可行,就无需再做其他尝试。这种思路不仅适用于回文串问题,在很多字符串匹配、数组遍历类题目中都能用到。
掌握这种双指针+辅助校验的模板,后续遇到「允许删除k个字符的回文校验」等进阶题目,也能快速上手。
#C语言进阶 #字符串算法 #双指针 #回文串问题 #CSDN学习打卡
欢迎来评论