无重复字符的最长子串
问题描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
思路关键词:滑动窗口、循环队列
代码实现:
#define MAX_SIZE (129)
// 实现一个循环队列
typedef struct {
char data[MAX_SIZE];
int front;
int rear;
} Queue;
Queue* initQueue() {
Queue* q = (Queue*) malloc(sizeof(Queue));
q->front = 0;
q->rear = 0;
return q;
}
void enQueue(Queue* q, char c) {
q->data[(q->rear)++] = c;
if (q->rear >= MAX_SIZE) {
q->rear = 0;
}
}
char deQueue(Queue* q) {
if (q->front == q->rear) {
return NULL;
}
char ret = q->data[(q->front)++];
if (q->front >= MAX_SIZE) {
q->front = 0;
}
return ret;
}
int getQueueLength(Queue* q) {
int ans = q->rear - q->front;
if (ans < 0) {
return ans + MAX_SIZE;
} else {
return ans;
}
}
int lengthOfLongestSubstring(char * s){
Queue* window = initQueue();
// 存储某个字符上次出现的下标(从1开始)
int* symbol = (int*) malloc(MAX_SIZE * sizeof(int));
int symbolIdx = 0;
int j;
for (j = 0;j < MAX_SIZE;j++) {
// 均初始化为-1
symbol[j] = -1;
}
int l = strlen(s);
// 结果
int ans = 0;
int i;
for (i = 0;i < l;i++) {
// 查看上一次是否出现
if (symbol[(int) s[i]] != -1) {
// 有出现,准备出队
int oldLen = getQueueLength(window);
if (oldLen >= ans) {
ans = oldLen;
}
int newIdx = symbol[(int) s[i]] - 1;
if (newIdx == -1) {
// 循环队列的特点
newIdx = MAX_SIZE - 1;
}
if ((window->front > window->rear && (newIdx >= window->front || newIdx < window->rear)) ||
((window->front < window->rear) && (newIdx >= window->front && newIdx < window->rear))) {
// 将队头指针移动到该位置
window->front = newIdx;
// 出队
deQueue(window);
}
}
// 入队
enQueue(window, s[i]);
// 记录这次的下标+1
symbol[(int) s[i]] = window->rear;
}
int finalLen = getQueueLength(window);
if (finalLen >= ans) {
ans = finalLen;
}
free(window);
free(symbol);
return ans;
}
最长回文子串
问题描述
给你一个字符串 s,找到 s 中最长的回文子串。
思路关键词:动态规划
详细思路:
- 设置二维动态规划数组 d p ( i , j ) dp(i, j) dp(i,j),表示字符串 s [ i , j ] s[i, j] s[i,j]是不是回文串
- 状态转移方程: d p ( i , j ) = { t r u e , i f j − i = 0 t r u e , i f j − i = 1 & & s [ i ] = s [ j ] f a l s e , i f j − i = 1 & & s [ i ] ≠ s [ j ] d p [ i + 1 ] [ j − 2 ] , i f j − i > 1 & & s [ i ] = s [ j ] f a l s e , i f j − i > 1 & & s [ i ] ≠ s [ j ] dp(i, j)=\left\{ \begin{matrix} true, \ \ if\ j-i=0 \\ true, \ \ if\ j-i=1\ \&\&\ s[i]=s[j] \\ false, \ \ if\ j-i=1\ \&\&\ s[i] ≠s[j] \\ dp[i+1][j-2], \ \ if\ j-i >1 \ \&\&\ s[i]=s[j] \\ false, \ \ if\ j-i >1 \ \&\&\ s[i]≠s[j] \end{matrix} \right. dp(i,j)=⎩ ⎨ ⎧true, if j−i=0true, if j−i=1 && s[i]=s[j]false, if j−i=1 && s[i]=s[j]dp[i+1][j−2], if j−i>1 && s[i]=s[j]false, if j−i>1 && s[i]=s[j]
代码实现如下:
char * longestPalindrome(char * s){
int l = strlen(s);
bool** dp = (bool**) malloc(l * sizeof(bool*));
int i, j;
for (i = 0;i < l;i++) {
dp[i] = (bool*) malloc(l * sizeof(bool));
for (j = 0;j < l;j++) {
dp[i][j] = false;
}
}
int ansX = 0;
int ansY = 0;
for (i = 0; i <= l-1;i++) {
for (j = 0;j <= l-1-i;j++) {
if (i == 0) {
dp[j][j+i] = true;
ansX = j;
ansY = j + i;
} else if (i == 1) {
if (s[j] == s[j+1]) {
dp[j][j+i] = true;
ansX = j;
ansY = j + i;
}
} else {
if (s[j] == s[j+i] && dp[j+1][j+i-1] == true) {
dp[j][j+i] = true;
ansX = j;
ansY = j + i;
}
}
}
}
char* palind = (char*) malloc((ansY - ansX + 2) * sizeof(char));
int palindIdx = 0;
for (i = ansX;i <= ansY;i++) {
palind[palindIdx++] = s[i];
}
palind[palindIdx] = '\0';
return palind;
}
字符串转换为整数
问题描述
请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
函数 myAtoi(string s) 的算法如下:
(1)读入字符串并丢弃无用的前导空格
(2)检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
(3)读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
(4)将前面步骤读入的这些数字转换为整数(即,“123” -> 123, “0032” -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
(5)如果整数数超过 32 位有符号整数范围 [−2^31, 2^31 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −2^31 的整数应该被固定为 −2^31 ,大于 2^31 − 1 的整数应该被固定为 2^31 − 1 。
(6)返回整数作为最终结果。
注意:
本题中的空白字符只包括空格字符 ’ ’ 。
除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。
思路关键词:有限状态机(DFA)
代码实现:
bool isDigit(char c) {
return (c >= '0') && (c <= '9');
}
int myAtoi(char * s){
/*
status: 状态机的状态序号
0:初始状态(--空格-->1, --符号-->2, --数字-->3,--其它-->4)
1:过滤前导空格(--空格-->1, --符号-->2, --数字-->3,--其它-->4)
2:读取到符号(--数字-->3,--其它-->4)
3:读取数字(--数字-->3,--其它-->4)
4:终止状态(跳出循环)
*/
int status = 0;
int sign = 1;
long ans = 0;
int idx = 0;
int l = strlen(s);
while (1) {
if (idx == l) break;
char c = s[idx++];
if (status == 0) {
if (c == ' ') {
status = 1;
} else if (c == '+') {
status = 2;
} else if (c == '-') {
sign = -1;
status = 2;
} else if (isDigit(c)) {
ans *= 10;
ans += (c - '0');
status = 3;
} else {
status = 4;
}
} else if (status == 1) {
if (c == ' ') {
continue;
} else if (isDigit(c)){
ans *= 10;
ans += (c - '0');
status = 3;
} else if (c == '+') {
status = 2;
} else if (c == '-') {
sign = -1;
status = 2;
} else {
status = 4;
}
} else if (status == 2) {
if (isDigit(c)) {
ans *= 10;
ans += (c - '0');
status = 3;
} else {
status = 4;
}
} else if (status == 3) {
if (isDigit(c)) {
// 判断越界
ans *= 10;
ans += (c - '0');
if (sign == 1) {
if (ans > 2147483647) {
ans = 2147483647;
status = 4;
continue;
}
} else {
if (ans > 2147483648) {
ans = 2147483648;
status = 4;
continue;
}
}
status = 3;
} else {
status = 4;
}
} else {
break;
}
}
if (ans == 2147483648) {
return (-2147483648);
} else {
return (sign * ((int) ans));
}
}