一、判断是否为回文数
【法一】粗暴反转
class Solution {
public boolean isPalindrome(int x) {
String s1 = Integer.toString(x);
StringBuilder sb = new StringBuilder(s1);
sb.reverse();
String s2 = sb.toString();
if(s1.equals(s2)){
return true;
}else{
return false;
}
}
}
【法二】左右两两比较
class Solution {
public boolean isPalindrome(int x) {
if(x < 0) return false;
int k=1;
//判断位数,如1221,得到k=1000
while(x/k>=10){
k = k*10;
}
while(x > 0){
int left = x / k;
int right = x % 10;
if(left != right){
return false;
}
x = (x % k) / 10; //1221 % 1000=221,221/10=22
k = k / 100; //k=10
}
return true;
}
}
【法三】取出一半进行翻转(想不到)
class Solution {
public boolean isPalindrome(int x) {
//思考:这里大家可以思考一下,为什么末尾为 0 就可以直接返回 false
if (x < 0 || (x % 10 == 0 && x != 0)) return false;
int revertedNumber = 0;
while (x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
return x == revertedNumber || x == revertedNumber / 10;
}
}
二、判断是否为回文链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null){
return true;
}
ListNode first = head;
ListNode temp = head;
int count=0;//链表长度
while(temp!=null){
temp = temp.next;
count++;
}
if(count==1){
return true;
}
ListNode mid = head;
for(int i=0;i<count/2;i++){
mid = mid.next;//mid到达链表后半段的头部
}
//翻转后半段链表
ListNode pre = null;
while(mid != null){
ListNode tmp = mid.next;
mid.next = pre;
pre = mid;
mid = tmp;
}
//此时pre成了后半段的头结点
if(count%2==0){
for(int j=0;j<count/2;j++){
if(first.val!=pre.val){
return false;
}
first = first.next;
pre = pre.next;
}
}else{ //考虑[1,0,1]的情况
for(int j=0;j<(count-1)/2;j++){
if(first.val!=pre.val){
return false;
}
first = first.next;
pre = pre.next;
}
}
return true;
}
}
三、最长回文数判断
Catcher 是MCA国的情报员,他工作时发现敌国会用一些对称的密码进行通信,比如像这些ABBA,ABA,A,123321,但是他们有时会在开始或结束时加入一些无关的字符以防止别国破解。比如进行下列变化 ABBA->12ABBA,ABA->ABAKK,123321->51233214 。因为截获的串太长了,而且存在多种可能的情况(abaaab可看作是aba,或baaab的加密形式),Cathcer的工作量实在是太大了,他只能向电脑高手求助,你能帮Catcher找出最长的有效密码串吗?
(注意:记得加上while处理多个测试用例)
——双指针法,从中间开始比较。
//使用对称的密码进行通信,会在首尾加入无关的字符
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String s = sc.nextLine();
char[] c = s.toCharArray();
int max=0;
for(int i=1;i<c.length;i++){
//寻找以i-1,i为中点的偶数长度回文数
int begin = i-1;
int end = i;
while(begin>=0 && end<c.length && c[begin]==c[end]){
begin--;
end++;
}
if(end-begin-1 > max){
max = end-begin-1;
}
//寻找以i为中心的奇数长度的回文数
begin = i-1;
end = i+1;
while(begin>=0 && end<c.length && c[begin]==c[end]){
begin--;
end++;
}
if(end-begin-1>max){
max=end-begin-1;
}
}
System.out.println(max);
}
}
}
四、最长回文子串
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
if(n<2){
return s;
}
int maxLen = 1;
int begin = 0;
for(int i = 0;i < n - 1;i++){
for(int j = i + 1;j < n;j++){
if(j - i + 1 > maxLen && judge(i,j,s)){
maxLen = j - i + 1;
begin = i;
}
}
}
return s.substring(begin,begin + maxLen);
}
public boolean judge(int i,int j,String s){
while(i<j){
if(s.charAt(i) == s.charAt(j)){
i++;
j--;
}else{
return false;
}
}
return true;
}
}
五、判断是否为回文字符串——正则表达式+双指针
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
class Solution {
public boolean isPalindrome(String s) {
//正则表达式,去除其他字符
String ss = s.replaceAll("[^a-zA-Z0-9]","");
ss = ss.toLowerCase();
int i=0;
int j = ss.length()-1;
while(i<j){
if(ss.charAt(i)==ss.charAt(j)){
i++;
j--;
}else{
return false;
}
}
return true;
}
}
六、删除一个字符,使之成为回文字符串——双指针,贪心算法
给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。
class Solution {
public boolean validPalindrome(String s) {
int i = 0;
int j = s.length()-1;
while(i<j){
if(s.charAt(i) != s.charAt(j)){
return judge(s,i+1,j) || judge(s,i,j-1);
}
i++;
j--;
}
return true;
}
public boolean judge(String s,int i,int j){
while(i<j){
if(s.charAt(i) == s.charAt(j)){
i++;
j--;
}else{
return false;
}
}
return true;
}
}
时间复杂度——O(n^2)
七、最长的回文子序列
【注意】子序列和子串不同,子串要求连续,子序列可以不连续,只要保证原有的顺序即可。
【例题】
LeetCode516:https://leetcode-cn.com/problems/longest-palindromic-subsequence/
给定一个字符串 s ,找到其中最长的回文子序列,并返回该序列的长度。可以假设 s 的最大长度为 1000 。
dp[i][j]表示从小标为i的位置到下标为j的位置间的元素。
class Solution {
public int longestPalindromeSubseq(String s) {
int n = s.length();
int[][] dp = new int[n][n];
for(int i=0;i<n;i++){
dp[i][i] = 1;
}
for(int i = n-2;i>=0;i--){
for(int j = i+1;j<n;j++){
if(s.charAt(i) == s.charAt(j)){
dp[i][j] = dp[i+1][j-1] + 2;
}else{
dp[i][j] = Math.max(dp[i+1][j],dp[i][j-1]);
}
}
}
return dp[0][n-1];
}
}