力扣——回文数系列

新春归来,写的第一篇博客,博客虽停 但是算法题还是有在刷,今个就总结一下回文数系列的题目。

回文数 即正序倒序都是一样的,如121,1221,aba,abcdedcba都是回文数

回文数字

上题来源牛客网56,今个力扣崩了进不去哈哈哈

我们很容易想到反转提供的数字或文字,但是数字容易溢出(即求余数再*10转化会超出Integer.MAX_VALUE),一个可行的方法是只反转一半。

public boolean isPalindrome (int x) {
        if(x==0) return true;
        if(x<0 || x%10==0) return false;//10 20 ...100和负数肯定不是回文数 直接排除
        int num=0;
        int tem=x;
        int rem=0;
        while(tem>num){
            rem=tem%10;
            num=num*10+rem;
            tem=tem/10;
        }
        return (num/10)==tem || num==tem;
    }

回文字符串

数字取余再反转,字符串呢?

我们也可以通过反转的方式求

a构建一个新的字符串 然后通过自带的api reverse()及equals() 比较

        if(str.length()<1) return false;
        
        StringBuffer tem=new StringBuffer();
        int n=str.length();
        for(int i=0;i<n;i++){
            tem.append(str.charAt(i));
        }
        //先将字符反转 再toString()
        return tem.reverse().toString().equals(str.toString());

注:

StringBuffer()  提供了字符串反转功能reverse()
StringBuffer()和String类型的字符进行比较时,通过tostring()后用equals()比较

b直接给StringBuffer()类赋值

StringBuffer()和String类并不等同,二者比较要先转化为string,

赋值的话可以挨个char字符赋值,直接赋值 可以如以下

        StringBuffer out=new StringBuffer();
        out.append(str);//String 和StringBuffer()  无法直接转化。
        return out.reverse().toString().equals(str.toString());

c不同过api,用双指针 挨个比较

        int n=str.length();
        int left=0;
        int right=n-1;
        while(left<right){
            if(str.charAt(left)!=str.charAt(right)){
                return false;
            }
            left++;
            right--;
        }

当然字符串可以设置一些其他要求:如只认定数字和字符

那么在给新的String赋值的时候 ,可以筛除一些。

# 判断但链表是否符合回文子串

单链表只能往下走不能回头

a设置快慢指针 对比

因为回文链表是关于中间结点(若存在)对称的,我们可以设置两个快慢指针(slow 和 fast)以获得中间结点。然后反转后部分链表 再和head挨个对比元素

        ListNode slow=head,fast=head;
        //01寻找到中间结点
        //偶数:slow 以后 包括 slow结点
        //奇数:slow.next之后都是
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        //分奇数偶数个结点
        if(fast!=null){
            //快指针 不为null 此链表为奇数个
            slow=slow.next;
        }
        
        //反转后半部分
        slow=reverseNode(slow);
        
        //比较head和slow链表
        while(slow!=null){
            if(slow.val!=head.val){
                return false;
            }
            slow=slow.next;
            head=head.next;
        }
        return true;

反转链表:

    private ListNode reverseNode(ListNode head){
        if(head==null || head.next==null) return head;
        ListNode res=reverseNode(head.next);
        head.next.next=head;
        head.next=null;
        return res;
    }

求链表是否为回文结构 还可以使用栈依次比较

b用递归求

先进入递归到最后一个
然后函数之外的head从头开始 这样就可以挨个比较了

public class Solution {

    ListNode temp;

    public boolean isPail (ListNode head) {
        // write code here
        temp=head;
        return check(head);
    }
    private boolean check(ListNode head){
        if(head==null) return true;
        boolean res=check(head.next) && (temp.val==head.val);
        temp=temp.next;
        return res;
    }
}

求字符串中打乱之后最长的回文子串

利用HashSet 求解最后保存个数

class Solution {
    public boolean canPermutePalindrome(String s) {
        //字符打乱 重新排列
        //那么一个字符串 
        //偶数: 所有字符数目都是双数
        //奇数: 一个奇数目+ 其他双数目

        //哈希表是键值对
        //HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
        if(s==null) return true;
        char[] c=s.toCharArray();
        Set<Character> m=new HashSet<>();
        for(char tem:c){
            if(m.contains(tem)){
                m.remove(tem);
            }else{
                m.add(tem);
            }
        }

        return m.size()<=1;
    }
}

最长回文子串

a中心扩散法

public class Solution {

    public int getLongestPalindrome (String A) {
        // write code here
        //中心扩散法
        int n=A.length();
        if(n<=1) return n;
        
        int longPal=0;//最长回文子串
        int left,right;
        for(int i=0 ; i<n ; ){
            //求解最长  longPal保存最长的
            if( (n-i) < longPal /2) break;
            left=right=i;
            
            //去除重复的  n-1  避免越界
            while(right < n-1 && A.charAt(right+1)==A.charAt(right)){
                ++right;
            }
            
            //修改i的位置
            i=right+1;
            while(left>0 && right<n-1 && A.charAt(right+1)==A.charAt(left-1)){
                left--;right++;
            }
            
            //保留最长的
            if( (right-left+1)>longPal ){
                longPal=( right-left+1 );
            }
            
        }
        
        return longPal;
    }
}

b动态规划解法

确定状态方程

初始边界

状态转移

01设置一个布尔类型的dp数组

02初始化 对角线 两组元素相同

03

如果两个字符相等 且相邻  那么这两个元素回文  dp[i][j]=true  

如果两个字符串相等 不相邻,但内部字符串回文 即回文 

(A.charAt(i)==A.charAt(j) && ((j+1==i) || dp[i-1][j+1])  )

参考:最长回文字串——动态规划

 两个细节之处  ab  回文最长为1

i是最末尾字符   j是开始字符   那么判断二者内部元素是否为回文 可用dp[i-1][j+1]

public class Solution {
    public int getLongestPalindrome (String A) {
        // write code here
        int n=A.length();
        if(n<=1) return n;
        boolean[][] dp=new boolean[n][n];
        int maxLen=1;
        for(int i=0;i<n;i++){//i行  j列
            dp[i][i]=true;
            for(int j=0;j< i ;j++){
                if(A.charAt(i)==A.charAt(j) && ((j+1==i) || dp[i-1][j+1])  ){//两种可能 1相邻相等 2不相邻相等 那么内部要回文(A.charAt(i-1)==A.charAt(j+1))
                    dp[i][j]=true;//判断内部  回文 dp[i-1][j+1]   j是后面的字幕  i是前面的字母 即最前面的
                }
                if(dp[i][j] && maxLen<(i-j+1)){
                    maxLen=i-j+1;
                }
            }
        }
        return maxLen;
    }
}

最长回文子序列                                                                              516                                                                                                                                                                                                                                 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值