|
| 1 | +# [Problem 1930: Unique Length-3 Palindromic Subsequences](https://leetcode.com/problems/unique-length-3-palindromic-subsequences/description/?envType=daily-question) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | +We want palindromes of length 3, so they must be of the form x y x (first and last characters equal). The only degrees of freedom are the outer character x and the middle character y. We need to count distinct strings "x y x" that appear as subsequences (not substrings). For a given outer character x, if we can find at least one occurrence of x before some position and at least one occurrence after that position, then any distinct character y that appears somewhere between the first and last occurrence of x will yield the palindrome x y x. So counting, for each outer letter x, the number of distinct letters present between the first and last occurrence of x gives the number of distinct palindromes with outer letter x. Sum over x (26 letters). That avoids double counting because each palindrome is determined uniquely by (x,y). |
| 5 | + |
| 6 | +## Refining the problem, round 2 thoughts |
| 7 | +- Edge cases: if a letter x appears fewer than 2 times (i.e., no index i<k with s[i]=s[k]=x), it contributes 0. |
| 8 | +- Implementation: compute first and last index for each letter. For letters with first < last, collect distinct letters in s[first+1:last] (a set or boolean array). Complexity: scanning interior for each letter could be up to 26 * n ~ 2.6e6 operations for n=1e5, which is fine. |
| 9 | +- Alternative: could compute prefix/suffix masks to avoid rescanning, but the simple approach is clear and fast enough. |
| 10 | +- Time complexity: O(26 * n) = O(n). Space: O(1) extra (constant 26-sized arrays). |
| 11 | + |
| 12 | +## Attempted solution(s) |
| 13 | +```python |
| 14 | +class Solution: |
| 15 | + def countPalindromicSubsequence(self, s: str) -> int: |
| 16 | + # record first and last occurrence for each lowercase letter |
| 17 | + first = [-1] * 26 |
| 18 | + last = [-1] * 26 |
| 19 | + for i, ch in enumerate(s): |
| 20 | + idx = ord(ch) - 97 |
| 21 | + if first[idx] == -1: |
| 22 | + first[idx] = i |
| 23 | + last[idx] = i |
| 24 | + |
| 25 | + ans = 0 |
| 26 | + # for each possible outer character, count distinct middle characters between first and last |
| 27 | + for c in range(26): |
| 28 | + if first[c] != -1 and first[c] < last[c]: |
| 29 | + seen = [False] * 26 |
| 30 | + for j in range(first[c] + 1, last[c]): |
| 31 | + seen[ord(s[j]) - 97] = True |
| 32 | + ans += sum(seen) |
| 33 | + return ans |
| 34 | +``` |
| 35 | +- Notes: |
| 36 | + - Approach: For each outer character x (26 options), find its first and last index; if they exist with first < last, count the number of distinct characters in between — each distinct middle character y gives a unique palindrome x y x. |
| 37 | + - Time complexity: O(26 * n) = O(n) where n = len(s). For n up to 1e5 this is fast. |
| 38 | + - Space complexity: O(1) extra (arrays of size 26). |
0 commit comments