正读倒读都一样的整数 ,这个应该是最简单的介绍了吧。
用程序怎么简单实现呢?
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
判断一个字符串是否是回文串
public class isPlalindrome {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串:");
String str = sc.nextLine();
System.out.println(isPlalindrome(str));
}
public static boolean isPlalindrome(String str) {
//将字符串转化为字符数组
char[] array=str.toCharArray();
int left=0,right=array.length-1;//记录数组的开始位置和结束位置
while(left<right)//开始位置小于结束位置时,进行判断 两位置处于对称位置上
{
if(array[left++]!=array[right--])//如果两位值的字符不相同 则不对称
return false;//返回false
}
//所有位除奇数位时的中间位均对应 返回true
return true;
}
}
这个程序应该不难理解
暴力法
* 求解字符串的最长回文串----暴力法 O(n^3)
* 通过两层循环找出字符串的所有子串 对每一个子串进行判断
* 将是回文串的子串储存 当有新的回文串时,比较记录中的回文串和当前回文串的长度
* 用较长的串替换当前串 如果两串长度相同,保留旧的
* PS:如果想保存所有的回文串 可以修改记录回文串的结构为String数组(链表、hash表都可以)
public static String longestPlalindrome(String original)
{
//非空判断
if((original==null)||original.length()==0)
{
return null;
}
//将字符串转换为字符数组
char[] oriArray=original.toCharArray();
int first=0;
int end=0;//当前字符串中回文串的始末位置 包含末位置
for(int i=0;i<oriArray.length-1;i++)//两次循环 查找字符串的所有子串
{
for(int j=i;j<oriArray.length;j++)
{
//判断子串是否为回文串
int left=i,right=j;//记录左侧右侧的位置
while(left<right)//左侧下标小于右侧下标时 比较未完成
{
if(oriArray[left]!=oriArray[right])
break;//如果出现对称位置不相等元素 则不是回文串跳出循环
//判断下一对称位置
left++;
right--;
}
if(left>=right)//是否比较完成 是字符串是否为回文串的判断条件
{
if(j-i>end-first)//查找到回文串 且长度大于当前存储的回文串长度
{
//替换当前回文串
first=i;
end=j;
}
}
}
}
//查找结束 将数组转化为字符串返回
return String.valueOf(oriArray, first, end+1);
}
动态规划
动态规划不是算法,是一种方法
为了改进暴力法,我们首先观察如何避免在验证回文时进行不必要的重复计算。考虑 “ababa” 这个示例。如果我们已经知道 “bab” 是回文,那么很明显, “ababa” 一定是回文,因为它的左首字母和右尾字母是相同的。
先看代码吧
public static String longestPalindrome2(String s) {
int len = s.length();
if(len <= 1) return s;
//字符串为空或者长度等于1,直接返回
boolean[][] dp = new boolean[len][len];
//记录每一个子串的状态,dp[i][j]=true表明,以i为起点,j为终点的子串是回文
int max = 0;
//最大回文长度
String ret = s.substring(0, 1);
//存放回文,初始化为s的第一个字符,假如该字符串没有回文,那就直接返回字符串的第一个字符
for(int r = 1; r < len; r++){
for(int l = 0; l < r; l++){
//这两个循环很关键,
if(s.charAt(r) == s.charAt(l) && (r - l <= 2 || dp[l+1][r-1])){
dp[l][r] = true;
if(max < r - l + 1) {
max = r - l + 1;
//max值更新
ret = new String(s.substring(l, r + 1));
//存放新的回文
}
}
}
}
return ret;
}
看懂了吗?一维数组?二维数组?如果要计算的字符串放到二位数组里面,你会惊奇的发现?s[a,b]是回文的话,是s[a]=s[b],轴对称的。
中心扩展算法
事实上,只需使用恒定的空间,我们就可以在 O(n^2)的时间内解决这个问题。我们观察到回文中心的两侧互为镜像。因此,回文可以从它的中心展开,并且只有 2n - 12n−1 个这样的中心。
public static String longestPalindrome(String s) {
if (s == null || s.length() < 1)
{
return "";
}
int start = 0, end = 0;
//子串在原字符串中的定位
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
//判断奇数个 abcba
int len2 = expandAroundCenter(s, i, i + 1);
//判断偶数个 abba
int len = Math.max(len1, len2);
//比较两个谁更长
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
//以上是不懂意思
}
return s.substring(start, end + 1);
}
/*
* @Author liuhaidong
* @Description 中心结点法
* @Date 9:50 2019/9/16 0016
**/
private static int expandAroundCenter(String s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
L--;
R++;
}
return R - L - 1;
}
就是那中间数,然后两边比较