力扣算法学习day40-1
647-回文字串
题目
代码实现
class Solution {
// 动态规划: 速度 5ms
// public int countSubstrings(String s) {
// char[] sList = s.toCharArray();
// // dp
// // dp[i][j]:表示i-j(左闭右开)的s的子字符串是否是回文字串,true表示是,false表示不是
// // 对于元素i和元素j,有两种情况:
// // 当sList[i] != sList[j]时:此时dp[i][j]一定为false,即当前表示的i-j的s的子字符串开头和结尾就不一样,
// // 可以判断不是回文字串。故迭代公式:dp[i][j] = flase;
// // 当sList[i] == sList[j]时,此时有三种情况:
// // 1.坐标i == j,说明当前是单个字符,示例1中可以看出单个字符是回文字串。
// // 2.坐标j - i == 1,说明当前是aa这种情况,所以只有两个字符组成,可以确定是回文字串。
// // 3.在上两种情况以外,则比如aba这种情况,则需要看i+1到j-1是否是回文字串,如果是,然后在它的基础上它的两边
// // 相当于是加上了两个相同的字符,那这个字符也应该是回文字串了,故如果dp[i+1][j-1] = true,则dp[i][j] = true;
// // 迭代公式汇总:
// // sList[i] != sList[j],dp[i][j] = false;
// // sList[i] == sList[j] && j - i <= 1,dp[i][j] = true;
// // sList[i] == sList[j] && j - i > 1 && dp[i+1][j-1],dp[i][j] = true;
// // 注:这里还要加上一个大条件,就是j >= i,因为dp的定义j就不能小于i.
// boolean[][] dp = new boolean[sList.length][sList.length];
// int result = 0;// 用于记录结果的数量
// // 初始化,初始化为false,即j >= i都需要去判断。
// // 遍历顺序:由迭代公式可以看出dp[i][j]的结果除了和j,i的差值有关系外,还和左下角dp[i+1][j-1]有关,
// // 所以需要先遍历从上到下或从下到上,不能先遍历横向,因为左下角dp[i+1][j-1]可能没有判断。
// for(int j = 0;j < sList.length;j++){
// for(int i = 0;i < sList.length;i++){
// if(j < i || sList[i] != sList[j]){
// continue;
// } else{
// if(j - i <= 1){
// dp[i][j] = true;
// result++;
// } else if(dp[i+1][j-1]){
// dp[i][j] = true;
// result++;
// }
// }
// }
// }
// return result;
// }
// 方法二: 双指针法 速度 1ms
public int countSubstrings(String s) {
char[] sList = s.toCharArray();
// 这个方法比较妙,它是遍历sList的元素,然后利用回文串的性质:两边元素相等,中间是回文串这个就是回文串,
// 然后,分为两种情况,一种是中心单个元素,第二个是中心是两个元素,方便理解的话,其实就是这两种情况覆盖
// 了奇数和偶数两种情况,一个元素向两边扩散的字符串只有奇数长度,两个为中心就是偶数,将这两种情况判断再
// 都加上即可。
int result = 0;
for(int i = 0;i < sList.length;i++){
result += doublePointResult(i,i,sList.length,sList);
result += doublePointResult(i,i+1,sList.length,sList);
}
return result;
}
public int doublePointResult(int i,int j,int length,char[] sList){
int result = 0;
while(i >= 0 && j < length && sList[i] == sList[j]){
result++;
i--;
j++;
}
return result;
}
}