题目描述
给定一个非空字符串 s
,请判断如果 最多 从字符串中删除一个字符能否得到一个回文字符串。
示例 1:
输入: s = "aba"
输出: true
示例 2:
输入: s = "abca"
输出: true
解释: 可以删除 "c" 字符 或者 "b" 字符
示例 3:
输入: s = "abc"
输出: false
提示:
1 <= s.length <= 105
s
由小写英文字母组成
注意:本题与主站 680 题相同: https://leetcode.cn/problems/valid-palindrome-ii/
解法
方法一:双指针
我们用两个指针 $i$ 和 $j$ 分别指向字符串 $s$ 的第一个字符和最后一个字符,然后向中间移动指针,每次判断 $s[i]$ 和 $s[j]$ 是否相等:
- 如果 $s[i] = s[j]$,则指针 $i$ 向后移动一位,指针 $j$ 向前移动一位;
- 否则,存在两种情况,即删除字符 $s[i]$ 或者删除字符 $s[j]$,然后判断删除之后的字符串是否是回文字符串。即判断子串 $s[i+1..j]$ 或者子串 $s[i..j-1]$ 是否是回文字符串。
时间复杂度 $O(n)$,其中 $n$ 是字符串 $s$ 的长度。空间复杂度 $O(1)$。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution:
def validPalindrome(self, s: str) -> bool:
def check(i: int, j: int) -> bool:
while i < j:
if s[i] != s[j]:
return False
i, j = i + 1, j - 1
return True
i, j = 0, len(s) - 1
while i < j:
if s[i] != s[j]:
return check(i + 1, j) or check(i, j - 1)
i, j = i + 1, j - 1
return True
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | class Solution {
private String s;
public boolean validPalindrome(String s) {
this.s = s;
for (int i = 0, j = s.length() - 1; i < j; ++i, --j) {
if (s.charAt(i) != s.charAt(j)) {
return check(i + 1, j) || check(i, j - 1);
}
}
return true;
}
private boolean check(int i, int j) {
for (; i < j; ++i, --j) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | class Solution {
public:
bool validPalindrome(string s) {
auto check = [&](int i, int j) {
for (; i < j; ++i, --j) {
if (s[i] != s[j]) {
return false;
}
}
return true;
};
for (int i = 0, j = s.size() - 1; i < j; ++i, --j) {
if (s[i] != s[j]) {
return check(i + 1, j) || check(i, j - 1);
}
}
return true;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | func validPalindrome(s string) bool {
check := func(i, j int) bool {
for ; i < j; i, j = i+1, j-1 {
if s[i] != s[j] {
return false
}
}
return true
}
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
if s[i] != s[j] {
return check(i+1, j) || check(i, j-1)
}
}
return true
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | function validPalindrome(s: string): boolean {
const check = (i: number, j: number): boolean => {
for (; i < j; ++i, --j) {
if (s[i] !== s[j]) {
return false;
}
}
return true;
};
for (let i = 0, j = s.length - 1; i < j; ++i, --j) {
if (s[i] !== s[j]) {
return check(i + 1, j) || check(i, j - 1);
}
}
return true;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | /**
* @param {string} s
* @return {boolean}
*/
var validPalindrome = function (s) {
const check = (i, j) => {
for (; i < j; ++i, --j) {
if (s[i] !== s[j]) {
return false;
}
}
return true;
};
for (let i = 0, j = s.length - 1; i < j; ++i, --j) {
if (s[i] !== s[j]) {
return check(i + 1, j) || check(i, j - 1);
}
}
return true;
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 | class Solution {
private var s: String = ""
func validPalindrome(_ s: String) -> Bool {
self.s = s
var i = s.startIndex
var j = s.index(before: s.endIndex)
while i < j {
if s[i] != s[j] {
return check(s.index(after: i), j) || check(i, s.index(before: j))
}
i = s.index(after: i)
j = s.index(before: j)
}
return true
}
private func check(_ i: String.Index, _ j: String.Index) -> Bool {
var i = i
var j = j
while i < j {
if s[i] != s[j] {
return false
}
i = s.index(after: i)
j = s.index(before: j)
}
return true
}
}
|