字符串:回文
# 0005. 最长回文子串 (opens new window)
题目
给你一个字符串 s
,找到 s
中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
2
3
示例 2:
输入:s = "cbbd"
输出:"bb"
2
提示:
1 <= s.length <= 1000
s
仅由数字和英文字母组成
中心扩展法,枚举回文子串的中心位置,每次循环需要分奇数和偶数两种情况。
代码
# 0009. 回文数 (opens new window)
题目
给你一个整数 x
,如果 x
是一个回文整数,返回 true
;否则,返回 false
。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
- 例如,
121
是回文,而123
不是。
示例 1:
输入:x = 121
输出:true
2
示例 2:
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
2
3
示例 3:
输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。
2
3
提示:
-2^31 <= x <= 2^31 - 1
进阶:你能不将整数转为字符串来解决这个问题吗?
本题可以借鉴 0007. 整数反转 的做法,将数字反转后判断是否与原数字相等。
代码
# 0125. 验证回文串 (opens new window)
题目
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
使用头尾双指针不断向中间移动直到相遇,同时移动过程中对比两指针指向的字符是否相同。
代码
class Solution {
public:
bool isPalindrome(string s) {
int l = 0, r = s.length() - 1;
while (l < r) {
while (l < r && !isalnum(s[l])) l++;
while (l < r && !isalnum(s[r])) r--;
if (tolower(s[l++]) != tolower(s[r--])) return false;
}
return true;
}
};
2
3
4
5
6
7
8
9
10
11
12
# 0131. 分割回文串 (opens new window)
题目
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
DFS 枚举每个子串的分割位置,而分割的依据就是保证当前子串是一个回文串,所以这就需要频繁的对任意截取的一个子串进行检查。
为了提高运行效率,可以在 DFS 之前预处理一个状态数组 f[i][j]
,用来表示字符串 s[i]
到 s[j]
这部分子串是不是一个回文串。
代码
class Solution {
int n;
vector<vector<bool>> f;
vector<vector<string>> ans;
vector<string> path;
public:
vector<vector<string>> partition(string s) {
n = s.length();
f = vector<vector<bool>>(n, vector<bool>(n));
for (int j = 0; j < n; j++) {
for (int i = 0; i <= j; i++) {
if (i == j) f[i][j] = true;
else f[i][j] = (s[i] == s[j]) && (i + 1 > j - 1 || f[i + 1][j - 1]);
}
}
dfs(s, 0);
return ans;
}
void dfs(string& s, int idx) {
if (idx == n) {
ans.push_back(path);
return;
}
for (int i = idx; i < n; i++) {
if (!f[idx][i]) continue;
path.push_back(s.substr(idx, i - idx + 1));
dfs(s, i + 1);
path.pop_back();
}
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 0132. 分割回文串 II (opens new window)
题目
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。
返回符合要求的 最少分割次数 。
定义 f[i]
为 s[0]
到 s[i]
这部分子串的最少分割次数,枚举最后一个子串的长度,进行状态递推。
同时在枚举过程中需要重复判断某个子串是否是回文串,所以还需要定义 g[i][j]
表示 s[i]
到 s[j]
这部分子串是不是一个回文串。
代码
class Solution {
public:
int minCut(string s) {
int n = s.length();
vector<vector<bool>> g(n, vector<bool>(n));
for (int j = 0; j < n; j++) {
for (int i = 0; i <= j; i++) {
if (i == j) g[i][j] = true;
else g[i][j] = (s[i] == s[j]) && (i + 1 > j - 1 || g[i + 1][j - 1]);
}
}
vector<int> f(n, INT_MAX);
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
if (!g[j][i]) continue;
if (j == 0) f[i] = 0;
else f[i] = min(f[i], f[j - 1] + 1);
}
}
return f[n - 1];
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 0214. 最短回文串 (opens new window)
题目
解析
代码
# 0266. 回文排列 (opens new window)
题目
解析
代码
# 0267. 回文排列 II (opens new window)
题目
解析
代码
# 0336. 回文对 (opens new window)
题目
解析
代码
# 0409. 最长回文串 (opens new window)
题目
解析
代码
# 0479. 最大回文数乘积 (opens new window)
题目
解析
代码
# 0564. 寻找最近的回文数 (opens new window)
题目
解析
代码