BB1-回文串判断
[[CB1-判断带头结点的单链表是否为回文结构]]
1.判断带头结点的单链表是否为回文结构
代码实现
| C |
|---|
| /**
* 判断字符串是否为回文(使用双指针法)
* @param str 输入字符串
* @return 是回文返回true,不是回文返回false
*/
bool is_true(char str[]) {
// 边界条件检查:空字符串或单字符认为是回文
if (str == NULL) {
return false;
}
int N = strlen(str); // C语言内置函数,计算字符串长度
// 使用双指针从两端向中间比较
for (int i = 0; i < N / 2; i++) {
// 比较对称位置的字符
if (str[i] != str[N - i - 1]) {
return false; // 发现不匹配,不是回文
}
}
return true; // 所有对称位置字符都匹配,是回文
}
|
| C |
|---|
| /**
* 优化版本:使用双指针技术(更直观)
* @param str 输入字符串
* @return 是回文返回true,不是回文返回false
*/
bool is_palindrome_two_pointers(char str[]) {
if (str == NULL) {
return false;
}
int left = 0; // 左指针
int right = strlen(str) - 1; // 右指针
// 双指针向中间移动,比较对应字符
while (left < right) {
if (str[left] != str[right]) {
return false; // 发现不匹配
}
left++; // 左指针右移
right--; // 右指针左移
}
return true; // 所有字符都匹配
}
|
| C |
|---|
| /**
* 忽略大小写和非字母数字字符的回文判断
* @param str 输入字符串
* @return 是回文返回true,不是回文返回false
*/
bool is_palindrome_alphanumeric(char str[]) {
if (str == NULL) {
return false;
}
int left = 0;
int right = strlen(str) - 1;
while (left < right) {
// 跳过左边的非字母数字字符
while (left < right && !isalnum(str[left])) {
left++;
}
// 跳过右边的非字母数字字符
while (left < right && !isalnum(str[right])) {
right--;
}
// 比较字符(忽略大小写)
if (tolower(str[left]) != tolower(str[right])) {
return false;
}
left++;
right--;
}
return true;
}
|
| C |
|---|
| /**
* 递归版本的回文判断
* @param str 输入字符串
* @param start 起始位置
* @param end 结束位置
* @return 是回文返回true,不是回文返回false
*/
bool is_palindrome_recursive_helper(char str[], int start, int end) {
// 基础情况:指针相遇或交错
if (start >= end) {
return true;
}
// 比较当前字符
if (str[start] != str[end]) {
return false;
}
// 递归检查内部字符
return is_palindrome_recursive_helper(str, start + 1, end - 1);
}
bool is_palindrome_recursive(char str[]) {
if (str == NULL) {
return false;
}
return is_palindrome_recursive_helper(str, 0, strlen(str) - 1);
}
|
算法执行流程图解
基本版本执行过程:
| Text Only |
|---|
| 字符串:"abcba" 长度N=5
比较过程:
i=0: str[0]='a' vs str[4]='a' → 相等
i=1: str[1]='b' vs str[3]='b' → 相等
i=2: i < N/2=2.5 不成立,循环结束
结果:返回true
|
双指针版本执行过程:
| Text Only |
|---|
| 字符串:"racecar"
执行过程:
left=0, right=6: 'r' vs 'r' → 相等,left=1, right=5
left=1, right=5: 'a' vs 'a' → 相等,left=2, right=4
left=2, right=4: 'c' vs 'c' → 相等,left=3, right=3
left=3, right=3: left < right 不成立,循环结束
结果:返回true
|
复杂字符串处理:
| Text Only |
|---|
| 字符串:"A man, a plan, a canal: Panama"
处理过程:
原始:A man, a plan, a canal: Panama
处理:Amanaplanacanalpanama
双指针比较:
left=0, right=20: 'A' vs 'a' → 忽略大小写后相等
left=1, right=19: 'm' vs 'm' → 相等
...以此类推
|
算法比较图解
| Text Only |
|---|
| 原字符串:r a c e c a r
索引: 0 1 2 3 4 5 6
方法1(原始):i < N/2
i=0: 比较 str[0] 和 str[6]
i=1: 比较 str[1] 和 str[5]
i=2: 比较 str[2] 和 str[4]
i=3: 3 < 3.5 不成立,结束
方法2(双指针):
left=0, right=6 → 比较后 left=1, right=5
left=1, right=5 → 比较后 left=2, right=4
left=2, right=4 → 比较后 left=3, right=3
left < right 不成立,结束
|
复杂度分析
时间复杂度:O(n)
- 比较次数:最多需要比较n/2对字符
- 字符串长度计算:O(n)(strlen函数)
- 总体时间复杂度:O(n)
空间复杂度:O(1)
- 辅助变量:只使用常数个变量(i, left, right等)
- 无额外存储:不需要额外的数据结构
- 总体空间复杂度:O(1)
算法优化版本
| C |
|---|
| /**
* 优化版本:提前终止和边界优化
*/
bool is_palindrome_optimized(char str[]) {
if (str == NULL) return false;
int len = strlen(str);
if (len <= 1) return true; // 空串或单字符
int left = 0;
int right = len - 1;
while (left < right) {
// 提前终止:发现不匹配立即返回
if (str[left] != str[right]) {
return false;
}
left++;
right--;
}
return true;
}
/**
* SIMD优化版本(理论):
* 可以使用SIMD指令并行比较多个字符
* 但实际效果有限,因为字符串长度通常不长
*/
|
性能测试对比
| C |
|---|
| // 性能测试函数
void performance_test() {
char* test_strings[] = {
"a",
"aa",
"aba",
"abba",
"racecar",
"A man, a plan, a canal: Panama",
"race a car",
"hello world"
};
int num_tests = sizeof(test_strings) / sizeof(test_strings[0]);
for (int i = 0; i < num_tests; i++) {
clock_t start = clock();
// 测试原始方法
for (int j = 0; j < 1000000; j++) {
is_true(test_strings[i]);
}
clock_t time1 = clock() - start;
// 测试双指针方法
start = clock();
for (int j = 0; j < 1000000; j++) {
is_palindrome_two_pointers(test_strings[i]);
}
clock_t time2 = clock() - start;
printf("字符串: %s\n", test_strings[i]);
printf("原始方法: %ld\n", time1);
printf("双指针方法: %ld\n", time2);
printf("-------------------\n");
}
}
|
错误处理完善版本
| C |
|---|
| /**
* 安全版本:添加完整的错误处理
*/
bool is_palindrome_safe(char str[]) {
// 参数验证
if (str == NULL) {
printf("错误:输入字符串为空指针\n");
return false;
}
// 空字符串处理
if (str[0] == '\0') {
return true; // 空字符串认为是回文
}
int len = strlen(str);
// 长度检查
if (len < 0) {
printf("错误:字符串长度异常\n");
return false;
}
// 双指针比较
int left = 0;
int right = len - 1;
while (left < right) {
if (str[left] != str[right]) {
return false;
}
left++;
right--;
}
return true;
}
|
实际应用场景
| C |
|---|
| /**
* 应用示例:回文检测器
*/
void palindrome_detector() {
char input[1000];
printf("回文检测器\n");
printf("输入字符串(输入'quit'退出):\n");
while (1) {
printf("> ");
if (fgets(input, sizeof(input), stdin) != NULL) {
// 移除换行符
input[strcspn(input, "\n")] = 0;
if (strcmp(input, "quit") == 0) {
break;
}
if (is_palindrome_alphanumeric(input)) {
printf("是回文!\n");
} else {
printf("不是回文。\n");
}
}
}
}
|
算法特点
核心思想:
利用字符串的对称性,从两端向中间比较对应位置的字符。
关键技术:
1. 对称比较:比较str[i]和str[N-i-1]
2. 双指针:left和right指针相向移动
3. 提前终止:发现不匹配立即返回
优势:
- 时间效率高:O(n)时间复杂度
- 空间效率高:O(1)空间复杂度
- 实现简单:逻辑清晰,易于理解
- 适用广泛:支持各种类型的回文检测
应用场景:
- 文本处理和验证
- 密码学中的回文检测
- 生物信息学(DNA序列分析)
- 游戏开发(回文游戏)
- 数据验证
扩展应用:
- 数字回文检测
- 链表回文检测
- 树结构回文检测
- 多语言回文支持
这种回文检测算法是字符串处理中的基础算法,在实际开发中应用广泛,具有很高的实用价值。