1. 最长回文子串<5>
题目:
给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
动态规划的特性:
- 后续的计算可以使用之前的计算结果
- 空间换时间
本题回文串本身就具有动态规划的特性
代码:
string longestPalindrome(string s) {
int n = s.size();
// 单个字符直接返回 (特殊情况)
if (n < 2) return s;
// 回文子串的最大长度
int maxLen = 1;
// 回文子串的起始位置
int begin = 0;
// dp[i][j] 表示s[i...j]是否是回文串
// n行n列个0
vector<vector<int>> dp(n,vector<int>(n));
for (int i = 0; i < n; i++) {
dp[i][i] = true; // 对角线设置为True,这样表示单个字符一定是回文串
}
// 递推开始
// 从列开始
for (int j = 1; j < n; j++) {
//填该列的数据
for (int i = 0; i < j; i++) {
// 如果两端字符不相等
if (s[i] != s[j]) dp[i][j] = false;
else{
// (j-1)-(i+1)+1< 2 即去除两端字符后,子串长度为0或1时,表示是回文串
if (j - i < 3) {
dp[i][j] = true;
}else{
// 参考之前的计算结果
dp[i][j] = dp[i + 1][j - 1];
}
}
// j - i + 1为子串长度 dp[i][j]表示是否为回文串
if (dp[i][j] && j - i + 1 > maxLen) {
maxLen = j - i + 1;
begin = i;
}
}
}
return s.substr(begin, maxLen);
}
2. N 字形变换<6>
题目:
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入:s = “PAYPALISHIRING”, numRows = 3
输出:“PAHNAPLSIIGYIR”
示例 2:
输入:s = “PAYPALISHIRING”, numRows = 4
输出:“PINALSIGYAHRPI”
解释:
P I N
A L S I G
Y A H R
P I
示例 3:
输入:s = “A”, numRows = 1
输出:“A”
代码:
class Solution {
public:
string convert(string s, int numRows) {
int n = s.length(), r = numRows;
// r=1只有一行 r>=n 只有一列
if ( r == 1 || r >= n) return s;
// 先向下填写r个字符,之后r-2列,每列填写1个字符 即r+r-2 = 2r-2 为周期 => 2r-2个字符为一个周期
int t = r * 2 - 2;
// 字符串共n个字符,共n/t个周期,每个周期r-1列
// 为保证向上取整 n+t
int c = (n + t) / t * (r - 1);
vector<string> mat(r, string(c, 0));
// i是字符指针,x y是二维数组坐标
for (int i = 0, x = 0, y = 0; i < n; i++) {
mat[x][y] = s[i];
// 这里是先填字符,然后移动坐标
if (i % t < r-1) {
x++; // 向下移动
}
else {
x--;
y++; // 向右上移动
}
}
string ans;
for (auto& row : mat) {
for (char ch : row) {
if (ch) {
ans += ch;
}
}
}
return ans;
}
};
3.整数翻转<7>
题目:
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 1:
输入:x = 123
输出:321
示例 2:
输入:x = -123
输出:-321
示例 3:
输入:x = 120
输出:21
示例 4:
输入:x = 0
输出:0
弹出 x 的末尾数字 digit
digit = x % 10
x /= 10
将数字 digit 推入 rev 末尾
rev = rev * 10 + digit
pass:其实判断条件可以简化的,因为x本身会被int限制,当x为正数并且位数和Integer.MAX_VALUE的位数相等时首位最大只能为2,所以逆转后不会出现res = Integer.MAX_VALUE / 10 && tmp > 2的情况,自然也不需要判断res==214748364 && tmp>7了,反之负数情况也一样
代码:
class Solution {
public:
int reverse(int x){
int res = 0;
while ( x != 0 )
{
int num = x % 10; // 个位数
x /= 10; // 除去个位数之后的数
// INT_MAX表示最大整数,INT_MIN表示最小整数
// 如果溢出
if (res > INT_MAX / 10 || res < INT_MIN / 10){
return 0;
}
// x将末尾数字 推入 res中
res = res * 10 + num;
}
return res;
}
};
4. 字符串转换整数 <8>
题目
https://leetcode.cn/problems/string-to-integer-atoi/
代码:
int myAtoi(string str) {
int res = 0;
int i = 0;
//默认符号为1
int flag = 1;
// 如果是空格,那么后移指针i
while (str[i] == ' ') { i++; }
// 如果遇到-,flag置为-1
if (str[i] == '-') { flag = -1; }
// 遇到符号依然后移指针
if (str[i] == '+' || str[i] == '-') { i++; }
// 这里是从高位的位置开始扫描
while (i < str.size() && isdigit(str[i])) {
// 数字型的字符串可以相减
// 若是不减去'0',直接转int 会变成ASCII
int r = str[i] - '0';
if (res > INT_MAX / 10 || (res == INT_MAX / 10 && r > 7)) {
return flag > 0 ? INT_MAX : INT_MIN;
}
// 字符翻转时,是从低位扫描,然后推入新数字中
// 这里要保持原数字顺序不表
res = res * 10 + r;
i++;
}
return flag > 0 ? res : -res;
}
5. 回文数<9>
题目:
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入:x = 121
输出:true
示例 2:
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。
用的方法是,转为字符串,然后翻转,再比较
代码:
bool isPalindrome(int x) {
// 转化为字符串
string s = to_string(x);
// 新建一个副本
string str_e = s;
// 翻转
reverse(str_e.begin(), str_e.end());
// 比较
return s == str_e;
}
python用习惯了,第一反应就是字符串翻转