方法一:整数反转法(推荐)
代码逐行解析
bool isPalindrome(int num) {
// 处理特殊情况:负数不是回文数
if (num < 0) return false;
// 个位数都是回文数(0-9)
if (num < 10) return true;
// 使用long类型防止反转后溢出
long reversed = 0;
// 保存原始值用于比较
int original = num;
// 反转整数算法
while (num > 0) {
// 取出最后一位数字并添加到反转数中
reversed = reversed * 10 + num % 10;
// 去掉最后一位数字
num /= 10;
}
// 比较原始数和反转数
return original == reversed;
}
详细解释(新手友好)
-
处理特殊情况:
-
if (num < 0) return false;
:负数不可能是回文数,比如 -121 反转后是 121-,不相等 -
if (num < 10) return true;
:0-9 都是回文数,因为单个数字正反都一样
-
-
防止溢出:
-
long reversed = 0;
:使用 long 类型(4字节或8字节)而不是 int,避免反转大数时溢出 -
例如:输入 2147483647(int最大值),反转后为 7463847412,超出 int 范围
-
-
反转算法核心:
-
reversed = reversed * 10 + num % 10;
:-
num % 10
:获取数字的最后一位 -
reversed * 10
:将已有数字左移一位(十进制) -
例如:处理 123:
-
第一次:reversed = 0*10 + 3 = 3
-
第二次:reversed = 3*10 + 2 = 32
-
第三次:reversed = 32*10 + 1 = 321
-
-
-
num /= 10;
:去掉最后一位-
例如:123 / 10 = 12
-
-
-
比较结果:
-
return original == reversed;
:检查反转后是否与原始数相等
-
使用示例
#include <iostream>
using namespace std;
int main() {
int num;
cout << "请输入一个整数: ";
cin >> num;
if (isPalindrome(num)) {
cout << num << " 是回文数" << endl;
} else {
cout << num << " 不是回文数" << endl;
}
return 0;
}
扩展知识:整数反转技巧
整数反转是编程中常见的技术,除了回文数判断,还可以用于:
-
数字逆序输出:
void reversePrint(int n) { while (n) { cout << n % 10; // 输出最后一位 n /= 10; } }
-
整数反转函数:
int reverseNumber(int n) { long reversed = 0; while (n) { reversed = reversed * 10 + n % 10; n /= 10; } return (reversed < INT_MIN || reversed > INT_MAX) ? 0 : reversed; }
-
判断回文数变种:
// 判断二进制回文数 bool isBinaryPalindrome(int n) { int reversed = 0, temp = n; while (temp) { reversed = (reversed << 1) | (temp & 1); temp >>= 1; } return n == reversed; }
方法二:双指针法(字符串)
代码逐行解析
bool isPalindrome(int num) {
// 负数不是回文数
if (num < 0) return false;
// 将整数转为字符串
string str = to_string(num);
// 初始化双指针:left指向开头,right指向末尾
int left = 0;
int right = str.length() - 1;
// 双指针向中间移动
while (left < right) {
// 比较左右指针指向的字符
if (str[left] != str[right]) {
return false; // 发现不同,不是回文
}
// 移动指针
left++;
right--;
}
// 所有字符匹配,是回文数
return true;
}
详细解释(新手友好)
-
字符串转换:
-
string str = to_string(num);
:将整数转为字符串 -
例如:123 → "123"
-
-
双指针初始化:
-
int left = 0;
:指向字符串开头 -
int right = str.length() - 1;
:指向字符串末尾 -
例如:"123" 长度=3,right 初始为 2(索引从0开始)
-
-
双指针比较:
-
while (left < right)
:当左指针在右指针左侧时继续 -
if (str[left] != str[right])
:比较两端的字符-
不同:立即返回 false(不是回文)
-
相同:继续比较
-
-
left++; right--;
:指针向中间移动
-
-
回文判断:
-
如果所有字符都匹配,循环结束后返回 true
-
使用示例(同方法一)
扩展知识:双指针技巧
双指针是解决数组/字符串问题的强大工具,除了回文判断,还可用于:
-
两数之和:
vector<int> twoSum(vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; sort(nums.begin(), nums.end()); while (left < right) { int sum = nums[left] + nums[right]; if (sum == target) return {left, right}; if (sum < target) left++; else right--; } return {}; }
-
移除元素:
int removeDuplicates(vector<int>& nums) { if (nums.empty()) return 0; int slow = 0; for (int fast = 1; fast < nums.size(); fast++) { if (nums[fast] != nums[slow]) { nums[++slow] = nums[fast]; } } return slow + 1; }
-
反转字符串:
void reverseString(vector<char>& s) { int left = 0, right = s.size() - 1; while (left < right) { swap(s[left], s[right]); left++; right--; } }
两种方法对比
特性 | 方法一(整数反转) | 方法二(双指针) |
---|---|---|
实现难度 | 中等 | 简单 |
性能 | 高(O(log n)) | 中(O(n)) |
内存使用 | 低(常数空间) | 中(需字符串空间) |
适用性 | 纯数字处理 | 也可处理字符串 |
溢出处理 | 需要特别注意 | 无此问题 |
新手友好 | 中等 | 高 |
实际应用场景
-
方法一适用场景:
-
性能敏感的数值计算
-
嵌入式系统(资源受限环境)
-
处理大数(结合 long 或 BigInteger)
-
-
方法二适用场景:
-
快速原型开发
-
需要同时处理字符串和数字
-
学习算法和数据结构阶段
-
为什么这样写?举例说明
示例1:121(回文数)
-
方法一:
-
原始数:121
-
反转过程:0 → 1 → 12 → 121
-
121 == 121 → 是回文数
-
-
方法二:
-
字符串:"121"
-
比较:str[0] vs str[2]('1' == '1')
-
比较:str[1] vs str[1]('2' == '2')
-
所有字符匹配 → 是回文数
-
示例2:123(非回文数)
-
方法一:
-
原始数:123
-
反转过程:0 → 3 → 32 → 321
-
123 != 321 → 不是回文数
-
-
方法二:
-
字符串:"123"
-
第一次比较:str[0] vs str[2]('1' != '3')
-
立即返回 false
-
示例3:-121(负数)
-
两种方法都会在第一行判断:if (num < 0) return false;
学习建议
-
新手学习路径:
图表
代码
下载
基础语法
方法三:双指针
理解字符串操作
方法一:整数反转
掌握数值算法
-
练习题目:
-
基础:判断回文字符串
-
进阶:找出范围内的所有回文数
-
挑战:寻找回文素数(如 131)
-
-
调试技巧:
// 在方法一中添加调试输出 while (num > 0) { cout << "num: " << num << " reversed: " << reversed << endl; reversed = reversed * 10 + num % 10; num /= 10; }
掌握这两种方法后,你不仅能解决回文数问题,还能理解更广泛的算法思想,为学习其他算法打下坚实基础。
C++ string 类型详解(新手向)
什么是 string?
string
是 C++ 标准库中提供的字符串类型,它封装了字符数组的操作,让字符串处理变得更简单、更安全。你可以把它想象成一个"智能字符数组",它会自动管理内存,并提供丰富的操作功能。
为什么需要 string?
在 C 语言中,我们使用字符数组 (char[]
) 和字符指针 (char*
) 来处理字符串,这需要手动管理内存,容易出现错误。C++ 的 string
解决了这些问题:
// C 语言方式(繁琐且容易出错)
char name[20];
strcpy(name, "Alice");
strcat(name, " Smith");
// C++ string 方式(简洁安全)
string name = "Alice";
name += " Smith";
基本用法
1. 包含头文件
#include <string> // 必须包含这个头文件
using namespace std; // 或者使用 std::string
2. 创建和初始化
string s1; // 空字符串
string s2 = "Hello"; // 直接赋值
string s3("World"); // 构造函数初始化
string s4(5, 'A'); // 创建 5 个 'A' 组成的字符串 -> "AAAAA"
3. 基本操作
string name = "Alice";
// 获取长度
int len = name.length(); // 或者 name.size()
// 访问字符
char first = name[0]; // 'A'
char last = name.at(4); // 'e'(更安全的方式)
// 修改内容
name[0] = 'a'; // 变成 "alice"
name += " Smith"; // 字符串拼接 -> "alice Smith"
4. 输入输出
string input;
// 输入单个单词(遇到空格停止)
cout << "Enter your name: ";
cin >> input;
// 输入整行(包含空格)
cout << "Enter your full name: ";
getline(cin, input);
5. 字符串比较
string s1 = "apple";
string s2 = "banana";
if (s1 == s2) {
cout << "Equal";
} else if (s1 < s2) {
cout << "apple comes before banana"; // 按字典序比较
}
在回文数判断中的应用
在我们之前的回文数判断方法三中,string
发挥了关键作用:
bool isPalindrome(int num) {
if (num < 0) return false;
// 1. 将整数转为字符串
string str = to_string(num);
// 2. 初始化双指针
int left = 0;
int right = str.length() - 1; // 获取字符串长度
// 3. 双指针比较
while (left < right) {
// 比较字符
if (str[left] != str[right]) {
return false;
}
// 移动指针
left++;
right--;
}
return true;
}
关键点解析:
-
to_string(num)
:将整数转换为字符串 -
str.length()
:获取字符串长度 -
str[left]
:访问字符串中的字符
string 的常用功能
1. 字符串拼接
string firstName = "John";
string lastName = "Doe";
// 三种拼接方式
string fullName1 = firstName + " " + lastName;
string fullName2 = firstName;
fullName2.append(" ").append(lastName);
firstName += " ";
firstName += lastName; // 现在 firstName 是 "John Doe"
2. 子字符串操作
string text = "Hello, World!";
// 提取子串
string greeting = text.substr(0, 5); // "Hello"
string world = text.substr(7, 5); // "World"
// 查找子串
size_t pos = text.find("World"); // 返回位置 7
if (pos != string::npos) {
cout << "Found at position: " << pos;
}
// 替换子串
text.replace(7, 5, "C++"); // "Hello, C++!"
3. 字符串转换
// 数字转字符串
int age = 25;
string ageStr = to_string(age); // "25"
// 字符串转数字
string numStr = "123";
int num = stoi(numStr); // 123
double pi = stod("3.14159"); // 字符串转double
4. 字符串修改
string message = "I like Java";
// 插入
message.insert(7, "learning "); // "I like learning Java"
// 删除
message.erase(7, 9); // 删除位置7开始的9个字符 -> "I like Java"
message.erase(7); // 删除位置7开始到结尾 -> "I like"
// 清空
message.clear(); // 空字符串
为什么在回文数判断中使用 string?
-
简化处理:直接操作字符比处理数字更直观
-
避免溢出问题:大数反转可能导致整数溢出
-
通用性强:同样的方法可以处理字符串回文
bool isStringPalindrome(string str) { int left = 0, right = str.length() - 1; while (left < right) { if (str[left++] != str[right--]) return false; } return true; }
内存管理(重要!)
string
自动管理内存,不需要手动分配/释放:
// 错误方式(C语言风格)
char* cstr = new char[100];
strcpy(cstr, "Hello");
delete[] cstr; // 必须手动释放
// 正确方式(C++ string)
string s = "Hello";
// 不需要手动释放,离开作用域自动销毁
练习建议
-
实现一个函数,统计字符串中某个字符出现的次数
-
实现字符串反转函数(不使用标准库reverse)
-
创建一个简单的用户注册系统,验证用户名和密码格式
-
读取文本文件并统计单词数量
总结
string
是 C++ 中处理文本的核心工具,它:
-
自动管理内存,使用安全
-
提供丰富的字符串操作功能
-
简化文本处理任务
-
是标准库中其他组件(如文件流、正则表达式)的基础
在回文数判断中,我们利用 string
的以下特性:
-
数字转字符串 (
to_string
) -
获取字符串长度 (
length()
) -
随机访问字符 (
[]
或at()
) -
双指针遍历
掌握 string
是成为 C++ 程序员的重要一步,它能显著提高你处理文本数据的能力和效率!
注:该代码是本人自己所写,可能不够好,不够简便,欢迎大家指出我的不足之处。如果遇见看不懂的地方,可以在评论区打出来,进行讨论,或者联系我。上述内容全是我自己理解的,如果你有别的想法,或者认为我的理解不对,欢迎指出!!!如果可以,可以点一个免费的赞支持一下吗?谢谢各位彦祖亦菲!!!!!