leetcode
leetcode 601 ~ 650
验证回文串 II

验证回文串 II

难度:

标签:

题目描述

代码结果

运行时间: 42 ms, 内存: 16.2 MB


/*
 * Problem: Given a string s, determine if it can become a palindrome by removing at most one character.
 * 
 * Approach:
 * 1. Convert the string to a list of characters.
 * 2. Use Java Stream to filter out the mismatched character.
 * 3. Check if the resulting substring is a palindrome after removing the mismatched character.
 */
 
import java.util.stream.IntStream;
 
public class Solution {
    public boolean validPalindrome(String s) {
        int left = 0, right = s.length() - 1;
        while (left < right) {
            if (s.charAt(left) != s.charAt(right)) {
                int finalLeft = left, finalRight = right;
                return IntStream.range(0, 2).anyMatch(i -> isPalindrome(s, finalLeft + i, finalRight - (1 - i)));
            }
            left++;
            right--;
        }
        return true;
    }
    
    private boolean isPalindrome(String s, int left, int right) {
        return IntStream.range(left, (right + left + 1) / 2)
                .allMatch(i -> s.charAt(i) == s.charAt(right - i + left));
    }
}
 

解释

方法:

这个题解采用了双指针的思路。首先判断原字符串是否是回文串,如果是,直接返回 True。如果不是,则使用两个指针 left 和 right 分别指向字符串的首尾。当左右指针指向的字符相等时,同时向中间移动;当遇到不相等的字符时,尝试删除左指针或右指针指向的字符,判断删除后的子串是否是回文串。如果删除任意一个字符后可以形成回文串,则返回 True,否则返回 False。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在判断删除左指针或右指针指向的字符后,为何没有继续使用双指针方法检查剩余子串是否为回文?
在本题解中,一旦遇到不匹配的字符,尝试通过删除左指针或右指针指向的字符来解决问题。这里使用了字符串切片来生成新的子串,并直接检查新子串是否为回文串。实际上,可以继续使用双指针策略来检查切片后的子串是否为回文,这样可以避免生成新的字符串,从而优化内存使用和可能的性能损失。不过,为了简化代码和直观展示思路,题解选择了直接使用字符串反转的方法来判断回文。
🦆
如果字符串长度非常大,切片操作会对性能有什么影响?有没有更高效的方式来检查子串是否为回文?
在Python中,字符串切片操作虽然方便,但在处理非常大的字符串时可能会导致显著的内存使用和性能损耗,因为它会创建原字符串的一个新副本。一种更高效的方法是继续使用双指针技术:在确定要删除一个字符后,根据删除点将双指针向内移动,然后继续检查剩余部分是否为回文。这样可以避免创建额外的字符串副本,只需在原字符串上操作,大幅减少内存和时间消耗。
🦆
当左右指针的字符不相等时,为什么选择两种可能(删除左指针或右指针指向的字符)都要检验,而不是只检查一种?
在验证可能的回文串时,单纯删除左指针或右指针指向的字符可能不足以确保找到正确的解决方案。例如,在字符串 'abca' 中,如果只选择删除 'b'(左指针指向的字符),则剩余 'aca' 仍然是回文;但如果只选择删除 'c'(右指针指向的字符),剩余 'aba' 也是回文。因此,为了全面验证,需要检查两种可能性。这确保了在面对不同情况时,能够找到所有可能的回文结构。
🦆
在双指针对比中,如果中间部分已经验证为非回文,是否还有必要继续检查删除一个字符后的情况?
题目允许删除一个字符来尝试形成回文串,这意味着即便中间部分验证为非回文,仍有可能通过删除一个恰当的字符使得整个字符串成为回文。这是题目的特殊要求之一,即允许一次删除操作来达成回文的条件。因此,即使遇到非回文的中间部分,我们也需要继续探索删除一个字符的可能性,来找到可能的回文解决方案。

相关问题

验证回文串

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串

字母和数字都属于字母数字字符。

给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false

 

示例 1:

输入: s = "A man, a plan, a canal: Panama"
输出:true
解释:"amanaplanacanalpanama" 是回文串。

示例 2:

输入:s = "race a car"
输出:false
解释:"raceacar" 不是回文串。

示例 3:

输入:s = " "
输出:true
解释:在移除非字母数字字符之后,s 是一个空字符串 "" 。
由于空字符串正着反着读都一样,所以是回文串。

 

提示:

  • 1 <= s.length <= 2 * 105
  • s 仅由可打印的 ASCII 字符组成