本文最后更新于:4 个月前

题目描述

给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

示例 1:

输入: “aba”
输出: True

示例 2:

输入: “abca”
输出: True
解释: 你可以删除c字符。

注意:

字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。

题解思路

我们先来看看最简单的情况,也就是不删除字符的情况,然后再递进看看删除情况。

  1. 不删除字符的情况

先考虑如果不允许删除字符,如何判断一个字符串是否是回文串?双指针!!!
定义左右指针left、right,初始时分别指向字符串的第一个字符和最后一个字符。
每次判断左右指针指向的字符是否相同,如果不相同,则不是回文串;如果相同,则将左右指针都往中间移动一位,直到左右指针相遇,则字符串是回文串。

  1. 删除1个字符的情况

在前面不删除的情况下,发现在找到不相等的元素时,[0, left) 和 (right, len(s) - 1] 这两部分已经判断过是回文,因此不用再次判断。

剩下的只需要再判断 [left, right] 区间中的字符串,即删除 left 或者 right 指向的元素,剩余的区间 (left, right] 或者 [left, right) 是否为回文串。

若 (left, right] 或者 [left, right) 为回文串,则说明删除了一个字符可以构成回文串。

注意的是:若删除过一次,则不是回文串。

如果左右指针从两端同时向中间走,那么:

第一步:
a       b       c       a
|                       |
left                  right
第二步:
a       b       c       a
        |       |
        left  right

第一步,左右指针遇到的元素相等,继续向中间走;
第二步,左右指针遇到的元素不等,则必须进行处理:我们必须删除其中的一个字符,然后再判断 剩余的所有字符 是否是回文串。

删除 b:
a       c       a

或者  

删除 c:
a       b       a

即判断 aca 或者 aba 是否为回文字符串。

看看官方给出的实例,辅助理解:

代码

class Solution {
    int del = 0;  // 记录删除节点的次数
    public boolean validPalindrome(String s) {
        int left = 0, right = s.length()-1; // left左指针 right右指针
        while(left < right){
            if(s.charAt(left) == s.charAt(right)){
                left++;
                right--;
            }else{
                // 不相等的话,若没有删除字符,则删除左边或右边的字符再判断
                // 若删除过一次,则不是回文串
                if(del == 0){
                    del++;
                    return validPalindrome(s.substring(left, right)) || validPalindrome(s.substring(left+1, right+1));
                }
                return false;
            }
        }
        return true;
        /* if(left > right) return true; */
    }
}

复杂度分析

时间复杂度:O(n)。其中 n 是字符串的长度。判断整个字符串是否是回文字符串的时间复杂度是 O(n),遇到不同字符时,判断两个子串是否是回文字符串的时间复杂度也都是 O(n)。
空间复杂度:O(1)。只需要维护有限的常量空间。

提交

YH0528.png


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

[转]给网页添加全局Js质感字体 上一篇
Linux root 模式 下一篇

 目录