|
1 |
| -# know when to use for/while loops, for this question, while loop is much better |
2 |
| -# try to make code not break on edge cases |
3 |
| -# use while loop to keep 2 pointers in range |
| 1 | +# https://leetcode.com/problems/longest-palindromic-substring |
| 2 | +# Classic string problem |
4 | 3 |
|
| 4 | +# expanding 2-pointers: O(n^2), much faster on average |
5 | 5 | def longestPalindrome(s: str) -> str:
|
6 |
| - longest = 1 |
7 |
| - out = s[0] |
8 |
| - for i in range(len(s)): # for every index (and pair of indices) |
9 |
| - |
10 |
| - start = end = i # center is one element |
11 |
| - while start >= 0 and end < len(s) and s[start] == s[end]: |
12 |
| - if end - start + 1 > longest: |
13 |
| - out = s[start:end + 1] |
14 |
| - longest = end - start + 1 |
15 |
| - start -= 1 |
16 |
| - end += 1 |
17 |
| - |
18 |
| - start, end = i, i + 1 # center is 2 elements |
19 |
| - while start >= 0 and end < len(s) and s[start] == s[end]: |
20 |
| - if end - start + 1 > longest: |
21 |
| - out = s[start:end + 1] |
22 |
| - longest = end - start + 1 |
23 |
| - start -= 1 |
24 |
| - end += 1 |
25 |
| - return out |
26 |
| - |
27 |
| - |
28 |
| -def dp_solution(s): |
29 | 6 | n = len(s)
|
30 |
| - dp = [[False] * n for _ in range(n)] |
31 |
| - res = s[0] # placeholder in case there is no longer palindrome |
| 7 | + l_ans = r_ans = 0 |
32 | 8 |
|
33 |
| - for i in range(n): # any single letter is a palindrome |
34 |
| - dp[i][i] = True |
| 9 | + for cent in range(n - 1): |
| 10 | + # odd case |
| 11 | + l = cent |
| 12 | + r = cent |
| 13 | + while 0 <= l and r < n and s[l] == s[r]: |
| 14 | + if r_ans - l_ans < r - l: |
| 15 | + l_ans = l |
| 16 | + r_ans = r |
| 17 | + l -= 1 |
| 18 | + r += 1 |
| 19 | + |
| 20 | + # even case |
| 21 | + l = cent |
| 22 | + r = cent + 1 |
| 23 | + while 0 <= l and r < n and s[l] == s[r]: |
| 24 | + if r_ans - l_ans < r - l: |
| 25 | + l_ans = l |
| 26 | + r_ans = r |
| 27 | + l -= 1 |
| 28 | + r += 1 |
| 29 | + |
| 30 | + return s[l_ans: r_ans + 1] |
| 31 | + |
| 32 | + |
| 33 | +print(longestPalindrome("abcbad")) |
35 | 34 |
|
36 |
| - for j in range(n): |
37 |
| - for i in range(j): |
38 |
| - if s[i] == s[j] and (dp[i + 1][j - 1] or j == i + 1): |
39 |
| - dp[i][j] = True |
40 |
| - if j - i + 1 > len(res): # longer than current longest |
41 |
| - res = s[i:j + 1] |
42 |
| - return res |
43 | 35 |
|
44 |
| -s = "a" |
45 |
| -print(longestPalindrome(s)) |
| 36 | +# DP solution: O(n^2) |
| 37 | +def longestPalindrome(s: str) -> str: |
| 38 | + n = len(s) |
| 39 | + dp = [[False] * n for _ in range(n)] |
| 40 | + |
| 41 | + # base cases: length 1 and 2 |
| 42 | + for i in range(n): |
| 43 | + dp[i][i] = True |
| 44 | + for i in range(n - 1): |
| 45 | + dp[i][i + 1] = (s[i] == s[i + 1]) |
| 46 | + |
| 47 | + # start with smaller segments |
| 48 | + for le in range(3, n + 1): |
| 49 | + for l in range(n - le + 1): |
| 50 | + r = l + le - 1 |
| 51 | + dp[l][r] = (s[l] == s[r]) and dp[l + 1][r - 1] |
| 52 | + |
| 53 | + # find largest valid one |
| 54 | + for le in reversed(range(1, n + 1)): |
| 55 | + for l in range(n - le + 1): |
| 56 | + r = l + le - 1 |
| 57 | + if dp[l][r]: |
| 58 | + return s[l:r + 1] |
0 commit comments