Leetcode——验证回文串1,2,3

1. 验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:
输入: “A man, a plan, a canal: Panama”
输出: true

示例 2:
输入: “race a car”
输出: false

(1)双指针

  • 左右指针互相比较,如不相同则返回
  • 注意:
  • (1)先去除大小写字母差异,使用String.toLowerCase方法
  • (2)去除特殊字符,最开始不知道Character.isLetterOrDigit(str(right))方法,逐一列举
class Solution {
    public boolean isPalindrome(String s) {
        if(s == null)
            return true;
        s = s.toLowerCase();
        char[] str = s.toCharArray();
        int left = 0, right = s.length() - 1;
        while(left < right){
            /*
            不知道Character.isLetterOrDigit(str(right))方法,沙雕了
            while(left < right && (str[left] == ',' || str[left] == ':' || str[left] == ' ' || str[left] == '.' || str[left] == '@' || str[left] == '#' || str[left] == '_' || str[left] == '/'))
                left++;
            while(left < right && (str[right] == ',' || str[right] == ':' || str[right] == ' ' || str[right] == '.' || str[right] == '@' || str[right] == '#' || str[right] == '_' || str[right] == '/'))
                right--;
            */
            while(left < right && !Character.isLetterOrDigit(str[left]))
                left++;
            while(left < right && !Character.isLetterOrDigit(str[right]))
                right--;
            if(str[left] != str[right])
                return false;
            left++;
            right--;
        }
        return true;
    }
}

2. 验证回文串2

在这里插入图片描述

(1)双指针(贪心)

每次判断两个指针指向的字符是否相同,如果相同,则更新指针,令 low = low + 1 和 high = high - 1,然后判断更新后的指针范围内的子串是否是回文字符串。如果两个指针指向的字符不同,则两个字符中必须有一个被删除,此时我们就分成两种情况:即删除左指针对应的字符,留下子串 s[low + 1], s[low + 1], …, s[high],或者删除右指针对应的字符,留下子串 s[low], s[low + 1], …, s[high - 1]。当这两个子串中至少有一个是回文串时,就说明原始字符串删除一个字符之后就以成为回文串。

class Solution {
    public boolean validPalindrome(String s) {
    	int left = 0;
        int right = s.length() - 1;

        while (left < right) {
            if(s.charAt(left) != s.charAt(right)){
                //分两种情况,一是右边减一,二是左边加一
                return isPalindrome(s, left, right-1) || isPalindrome(s, left+1, right);
            }
            left++;
            right--;
        }
        return true;
    }

    public boolean isPalindrome(String s, int i, int j) {
        while (i < j) {
            if (s.charAt(i++) != s.charAt(j--)) {
                return false;
            }
        }
        return true;
    }
}

3. 验证回文串 3

在这里插入图片描述

(1)最长回文子序列dp,存在长度为n-k的即可

状态:

  • dp[i][j] 表示 s 的第 i 个字符到第 j 个字符组成的子串中,最长的回文序列长度是多少。

转移方程:

  • 如果 s 的第 i 个字符和第 j 个字符相同的话: dp[i][j] = dp[i + 1][j - 1] + 2
  • 如果 s 的第 i 个字符和第 j 个字符不同的话: dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
  • 然后注意遍历顺序,i 从最后一个字符开始往前遍历,j 从 i + 1 开始往后遍历,这样可以保证每个子问题都已经算好了。
    • 从递推公式dp[i][j] = dp[i + 1][j - 1] + 2 和 dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]) 可以看出,dp[i][j]是依赖于dp[i + 1][j - 1] 和 dp[i + 1][j],
    • 如果我们想求dp[i][j],那么其他3个必须都是已知的,很明显从上往下遍历是不行的,我们只能让i从最后一个字符往前遍历,j从i的下一个开始遍历,最后只需要返回dp[0][length - 1]即可。
      在这里插入图片描述

初始化:

  • dp[i][i] = 1 单个字符的最长回文序列是 1

字符串长度 - 最长子序列 <= k 即可:

class Solution {
    public boolean isValidPalindrome(String s, int k) {
        int len = s.length();
        int[][] dp = new int[len][len];
        for(int i = len-1; i >= 0; --i) {
            for(int j = i; j < len; ++j) {
                if(i == j) {
                    dp[i][j] = 1;
                    continue;
                } 
                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 len - dp[0][len-1] <= k;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yawn__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值