Given a string s, return the number of unique palindromes of length three that are a subsequence of s.

Note that even if there are multiple ways to obtain the same subsequence, it is still only counted once.

A palindrome is a string that reads the same forwards and backwards.

A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.

Input: s = "aabca"
Output: 3
Explanation: There are 3 palindromic subsequences of length 3
- "aaa" subsequence of "aabca"
- "aba" subsequence of "aabca"
- "aba" subsequence of "aabca"
Input: s = "adc"
Output: 0
Explanation: There are no palindromic subsequences with length 3.
Constraints:

Contents

The main intution of this approach is that for any given character at ith index, there are only 26 palindromes possible with length 3, for example if the middle character is 'a' inorder to have a palindrome with length 3, left and right side characters have to be one of the letters from 'a' to 'z', for example aaa, bab... zaz.

In this approach, we are going to use a HashMap, and two HashSets.

Then, we will loop through each character from input string s:

Example:

Lets look at an example with s = "aabca".

  • Finally, we will return our answer as 3, since we have found 3 unique palindromes with length 3.
  • In the above implementation, for every character we have looped through from a to z, if you are looking for bit more optimization here, we can just loop through left HashSet itself, at most it will have 26 characters or less.

    import java.util.HashMap; import java.util.HashSet; public class UniqueLength3PalindromicSubsequence { static int countPalindromicSubsequence(String s) { // First count each letter occurrence and its count HashMap<Character, Integer> right = new HashMap<>(); for(char c: s.toCharArray()) { right.merge(c, 1, Integer::sum); } HashSet<Character> left = new HashSet<>(); HashSet<String> uniquePalindromes = new HashSet<>(); // now loop through every character of string and check if left and right side characters are same for(char c: s.toCharArray()) { int newCount = right.merge(c, -1, Integer::sum); if(newCount == 0) { right.remove(c); } for(Character leftChar: left) { if(right.containsKey(leftChar)) { // this is a palindrome uniquePalindromes.add(String.valueOf(c) +leftChar);// just adding 2 letters, // as left and right letters will be same // in 3 letters palindromes } } left.add(c); } return uniquePalindromes.size(); } public static void main(String[] args) { System.out.println(countPalindromicSubsequence("aabca")); System.out.println(countPalindromicSubsequence("adc")); } }
    Complexity Analysis:

    Time complexity: Above code runs in O(n) time where n is the length of input string s (for every character, we are looping thorugh lowercase alphabets 26, since this is constant number we can ignore it).
    Space complexity: O(n)

    Above implementations source code can be found at GitHub link for Java code