Archived
valid palindrome II
An old note — I haven't updated it since I wrote it.
This is one of those questions where i really get to see how quickly i'm currently progressing.
My most recent answer:
1class Solution:
2 def validPalindrome(self, s: str) -> bool:
3 def is_pal(s, error=False):
4 for i in range(len(s)//2):
5 if s[i] != s[~i]:
6 if error:
7 return False
8 return is_pal(s[i+1:len(s)-i], True) or is_pal(s[i:len(s)-i-1], True)
9 return True
10 return is_pal(s)
It's:
- easy to read
- simple yet sophisticated ([[list index complement]])
- efficient (beats 75%)
- in-place
- uses recursion tastefully
my previous solution was a mess
This is in severe contrast with my previous solution, which was an utter mess. Hard to believe i wrote this only two weeks ago.
1class Solution:
2 def validPalindrome(self, s: str) -> bool:
3
4 def try_left(l):
5 if l + 1 == r:
6 return True, l+1
7 if s[l + 1] == s[r] and s[l + 2] == s[r - 1]:
8 return True, l+1
9 return False, l
10
11 def try_right(r):
12 if r - 1 == l:
13 return True, r-1
14 if s[r - 1] == s[l] and s[r - 2] == s[l + 1]:
15 return True, r-1
16 return False, r
17
18
19 l, r, skipped_one = 0, len(s)-1, False
20 while l <= r:
21 if s[l] == s[r]:
22 l += 1
23 r -= 1
24 else:
25 if skipped_one:
26 return False
27 left_skip_ok, l = try_left(l)
28 if left_skip_ok:
29 skipped_one = True
30 continue
31 right_skip_ok, r = try_right(r)
32 if right_skip_ok:
33 skipped_one = True
34 continue
35 return False
36 return True